blob: d05cb75f98932f18af4fc3bb9cde21851217a8cc [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Lingfeng Yangf97641c2018-06-21 19:22:45 -070025#include "libANGLE/queryutils.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040026#include "libANGLE/validationES2.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29#include "common/mathutil.h"
30#include "common/utilities.h"
31
Jamie Madille2e406c2016-06-02 13:04:10 -040032using namespace angle;
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034namespace gl
35{
Jamie Madill1ca74672015-07-21 15:14:11 -040036namespace
37{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050038bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
39{
40 // List of compressed format that require that the texture size is smaller than or a multiple of
41 // the compressed block size.
42 switch (internalFormat)
43 {
44 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
46 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
47 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
48 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
52 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
53 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59 return true;
jchen10a99ed552017-09-22 08:10:32 +080060
Luc Ferron9dbaeba2018-02-01 07:26:59 -050061 default:
62 return false;
63 }
64}
65bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
66{
67 // Compressed sub textures have additional formats that requires exact size.
68 // ES 3.1, Section 8.7, Page 171
69 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
70 IsETC2EACFormat(internalFormat);
71}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030072
73bool DifferenceCanOverflow(GLint a, GLint b)
74{
75 CheckedNumeric<GLint> checkedA(a);
76 checkedA -= b;
77 // Use negation to make sure that the difference can't overflow regardless of the order.
78 checkedA = -checkedA;
79 return !checkedA.IsValid();
80}
81
Jamie Madill2da53562018-08-01 11:34:47 -040082bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040083{
Jamie Madill51af38b2018-04-15 08:50:56 -040084 // If we're drawing zero vertices, we have enough data.
Jamie Madill2da53562018-08-01 11:34:47 -040085 ASSERT(primcount > 0);
Jamie Madill51af38b2018-04-15 08:50:56 -040086
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040087 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
88 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
Jamie Madill1ca74672015-07-21 15:14:11 -040089 {
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040090 return true;
Jamie Madill02c9c042018-04-17 13:43:48 -040091 }
James Darpiniane8a93c62018-01-04 18:02:24 -080092
Jamie Madill88602e62018-08-08 12:49:30 -040093 // An overflow can happen when adding the offset. Check against a special constant.
94 if (context->getStateCache().getNonInstancedVertexElementLimit() ==
95 VertexAttribute::kIntegerOverflow ||
96 context->getStateCache().getInstancedVertexElementLimit() ==
97 VertexAttribute::kIntegerOverflow)
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040098 {
99 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
100 return false;
101 }
102
103 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
104 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
106 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400107}
108
Jamie Madill5b772312018-03-08 20:28:32 -0500109bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400110{
111 switch (type)
112 {
113 // Types referenced in Table 3.4 of the ES 2.0.25 spec
114 case GL_UNSIGNED_BYTE:
115 case GL_UNSIGNED_SHORT_4_4_4_4:
116 case GL_UNSIGNED_SHORT_5_5_5_1:
117 case GL_UNSIGNED_SHORT_5_6_5:
118 return context->getClientVersion() >= ES_2_0;
119
120 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
121 case GL_BYTE:
122 case GL_INT:
123 case GL_SHORT:
124 case GL_UNSIGNED_INT:
125 case GL_UNSIGNED_INT_10F_11F_11F_REV:
126 case GL_UNSIGNED_INT_24_8:
127 case GL_UNSIGNED_INT_2_10_10_10_REV:
128 case GL_UNSIGNED_INT_5_9_9_9_REV:
129 case GL_UNSIGNED_SHORT:
130 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
131 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
132 return context->getClientVersion() >= ES_3_0;
133
134 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400135 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
136 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400137
138 case GL_HALF_FLOAT:
139 return context->getClientVersion() >= ES_3_0 ||
140 context->getExtensions().textureHalfFloat;
141
142 case GL_HALF_FLOAT_OES:
143 return context->getExtensions().colorBufferHalfFloat;
144
145 default:
146 return false;
147 }
148}
149
Jamie Madill5b772312018-03-08 20:28:32 -0500150bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400151{
152 switch (format)
153 {
154 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
155 case GL_RGBA:
156 case GL_RGB:
157 case GL_ALPHA:
158 return context->getClientVersion() >= ES_2_0;
159
160 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
161 case GL_RG:
162 case GL_RED:
163 case GL_RGBA_INTEGER:
164 case GL_RGB_INTEGER:
165 case GL_RG_INTEGER:
166 case GL_RED_INTEGER:
167 return context->getClientVersion() >= ES_3_0;
168
169 case GL_SRGB_ALPHA_EXT:
170 case GL_SRGB_EXT:
171 return context->getExtensions().sRGB;
172
173 case GL_BGRA_EXT:
174 return context->getExtensions().readFormatBGRA;
175
176 default:
177 return false;
178 }
179}
180
Jamie Madill5b772312018-03-08 20:28:32 -0500181bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400182 GLenum framebufferComponentType,
183 GLenum format,
184 GLenum type)
185{
186 switch (framebufferComponentType)
187 {
188 case GL_UNSIGNED_NORMALIZED:
189 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
190 // ReadPixels with BGRA even if the extension is not present
191 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
192 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
193 type == GL_UNSIGNED_BYTE);
194
195 case GL_SIGNED_NORMALIZED:
196 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
197
198 case GL_INT:
199 return (format == GL_RGBA_INTEGER && type == GL_INT);
200
201 case GL_UNSIGNED_INT:
202 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
203
204 case GL_FLOAT:
205 return (format == GL_RGBA && type == GL_FLOAT);
206
207 default:
208 UNREACHABLE();
209 return false;
210 }
211}
212
Geoff Langc1984ed2016-10-07 12:41:00 -0400213template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400214bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400215{
216 switch (ConvertToGLenum(params[0]))
217 {
218 case GL_CLAMP_TO_EDGE:
219 break;
220
221 case GL_REPEAT:
222 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400223 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400224 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400225 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700226 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400227 return false;
228 }
229 break;
230
231 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400233 return false;
234 }
235
236 return true;
237}
238
239template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400240bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400241{
242 switch (ConvertToGLenum(params[0]))
243 {
244 case GL_NEAREST:
245 case GL_LINEAR:
246 break;
247
248 case GL_NEAREST_MIPMAP_NEAREST:
249 case GL_LINEAR_MIPMAP_NEAREST:
250 case GL_NEAREST_MIPMAP_LINEAR:
251 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400252 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400253 {
254 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400256 return false;
257 }
258 break;
259
260 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400262 return false;
263 }
264
265 return true;
266}
267
268template <typename ParamType>
269bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
270{
271 switch (ConvertToGLenum(params[0]))
272 {
273 case GL_NEAREST:
274 case GL_LINEAR:
275 break;
276
277 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400279 return false;
280 }
281
282 return true;
283}
284
285template <typename ParamType>
286bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
287{
288 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
289 switch (ConvertToGLenum(params[0]))
290 {
291 case GL_NONE:
292 case GL_COMPARE_REF_TO_TEXTURE:
293 break;
294
295 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700296 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400297 return false;
298 }
299
300 return true;
301}
302
303template <typename ParamType>
304bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
305{
306 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
307 switch (ConvertToGLenum(params[0]))
308 {
309 case GL_LEQUAL:
310 case GL_GEQUAL:
311 case GL_LESS:
312 case GL_GREATER:
313 case GL_EQUAL:
314 case GL_NOTEQUAL:
315 case GL_ALWAYS:
316 case GL_NEVER:
317 break;
318
319 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400321 return false;
322 }
323
324 return true;
325}
326
327template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700328bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
329{
330 if (!context->getExtensions().textureSRGBDecode)
331 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700333 return false;
334 }
335
336 switch (ConvertToGLenum(params[0]))
337 {
338 case GL_DECODE_EXT:
339 case GL_SKIP_DECODE_EXT:
340 break;
341
342 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700344 return false;
345 }
346
347 return true;
348}
349
Luc Ferron1b1a8642018-01-23 15:12:01 -0500350bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
351{
352 if (!context->getExtensions().textureFilterAnisotropic)
353 {
354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
355 return false;
356 }
357
358 return true;
359}
360
361bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
362{
363 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
364 {
365 return false;
366 }
367
368 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
369
370 if (paramValue < 1 || paramValue > largest)
371 {
372 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
373 return false;
374 }
375
376 return true;
377}
378
Jamie Madill5b772312018-03-08 20:28:32 -0500379bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400380{
381 const Program *program = context->getGLState().getProgram();
382 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
383
Jamie Madille7d80f32018-08-08 15:49:23 -0400384 return ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
385 framebuffer->getDrawBufferTypeMask().to_ulong(),
386 program->getActiveOutputVariables().to_ulong(),
387 framebuffer->getDrawBufferMask().to_ulong());
Geoff Lange0cff192017-05-30 13:04:56 -0400388}
389
Jamie Madill5b772312018-03-08 20:28:32 -0500390bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400391{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700392 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400393 const Program *program = context->getGLState().getProgram();
394 const VertexArray *vao = context->getGLState().getVertexArray();
395
Brandon Jonesc405ae72017-12-06 14:15:03 -0800396 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
397 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
398 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
399
400 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
401 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
402 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
403
Jamie Madille7d80f32018-08-08 15:49:23 -0400404 return ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(),
405 vaoAttribTypeBits, program->getAttributesMask().to_ulong(),
406 0xFFFF);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400407}
408
Jamie Madill493f9572018-05-24 19:52:15 -0400409bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
410 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800411{
412 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400413 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800414 {
Jamie Madill493f9572018-05-24 19:52:15 -0400415 case PrimitiveMode::Points:
416 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
417 case PrimitiveMode::Lines:
418 case PrimitiveMode::LineStrip:
419 case PrimitiveMode::LineLoop:
420 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
421 case PrimitiveMode::LinesAdjacency:
422 case PrimitiveMode::LineStripAdjacency:
423 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
424 case PrimitiveMode::Triangles:
425 case PrimitiveMode::TriangleFan:
426 case PrimitiveMode::TriangleStrip:
427 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
428 case PrimitiveMode::TrianglesAdjacency:
429 case PrimitiveMode::TriangleStripAdjacency:
430 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800431 default:
432 UNREACHABLE();
433 return false;
434 }
435}
436
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700437// GLES1 texture parameters are a small subset of the others
438bool IsValidGLES1TextureParameter(GLenum pname)
439{
440 switch (pname)
441 {
442 case GL_TEXTURE_MAG_FILTER:
443 case GL_TEXTURE_MIN_FILTER:
444 case GL_TEXTURE_WRAP_S:
445 case GL_TEXTURE_WRAP_T:
446 case GL_TEXTURE_WRAP_R:
447 case GL_GENERATE_MIPMAP:
448 case GL_TEXTURE_CROP_RECT_OES:
449 return true;
450 default:
451 return false;
452 }
453}
Geoff Langf41a7152016-09-19 15:11:17 -0400454} // anonymous namespace
455
Brandon Jonesd1049182018-03-28 10:02:20 -0700456void SetRobustLengthParam(GLsizei *length, GLsizei value)
457{
458 if (length)
459 {
460 *length = value;
461 }
462}
463
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500464bool IsETC2EACFormat(const GLenum format)
465{
466 // ES 3.1, Table 8.19
467 switch (format)
468 {
469 case GL_COMPRESSED_R11_EAC:
470 case GL_COMPRESSED_SIGNED_R11_EAC:
471 case GL_COMPRESSED_RG11_EAC:
472 case GL_COMPRESSED_SIGNED_RG11_EAC:
473 case GL_COMPRESSED_RGB8_ETC2:
474 case GL_COMPRESSED_SRGB8_ETC2:
475 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
476 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
477 case GL_COMPRESSED_RGBA8_ETC2_EAC:
478 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
479 return true;
480
481 default:
482 return false;
483 }
484}
485
Jamie Madill5b772312018-03-08 20:28:32 -0500486bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400487{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800488 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400489 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800490 case TextureType::_2D:
491 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800492 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400493
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800494 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400495 return context->getExtensions().textureRectangle;
496
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800497 case TextureType::_3D:
498 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800499 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500500
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800501 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800502 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400503
He Yunchaoced53ae2016-11-29 15:00:51 +0800504 default:
505 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500506 }
Jamie Madill35d15012013-10-07 10:46:37 -0400507}
508
Jamie Madill5b772312018-03-08 20:28:32 -0500509bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500510{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800511 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500512 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800513 case TextureType::_2D:
514 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500515 return true;
516
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800517 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400518 return context->getExtensions().textureRectangle;
519
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500520 default:
521 return false;
522 }
523}
524
Jamie Madill5b772312018-03-08 20:28:32 -0500525bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500526{
527 switch (target)
528 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800529 case TextureType::_3D:
530 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300531 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500532
533 default:
534 return false;
535 }
536}
537
Ian Ewellbda75592016-04-18 17:25:54 -0400538// Most texture GL calls are not compatible with external textures, so we have a separate validation
539// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500540bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400541{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800542 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400543 (context->getExtensions().eglImageExternal ||
544 context->getExtensions().eglStreamConsumerExternal);
545}
546
Shannon Woods4dfed832014-03-17 20:03:39 -0400547// This function differs from ValidTextureTarget in that the target must be
548// usable as the destination of a 2D operation-- so a cube face is valid, but
549// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400550// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500551bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400552{
553 switch (target)
554 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800555 case TextureTarget::_2D:
556 case TextureTarget::CubeMapNegativeX:
557 case TextureTarget::CubeMapNegativeY:
558 case TextureTarget::CubeMapNegativeZ:
559 case TextureTarget::CubeMapPositiveX:
560 case TextureTarget::CubeMapPositiveY:
561 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800562 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800563 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400564 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800565 default:
566 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500567 }
568}
569
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800570bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400571 PrimitiveMode transformFeedbackPrimitiveMode,
572 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800573{
574 ASSERT(context);
575
576 if (!context->getExtensions().geometryShader)
577 {
578 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
579 // that does not match the current transform feedback object's draw mode (if transform
580 // feedback is active), (3.0.2, section 2.14, pg 86)
581 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
582 }
583
584 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400585 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800586 {
Jamie Madill493f9572018-05-24 19:52:15 -0400587 case PrimitiveMode::Points:
588 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
589 case PrimitiveMode::Lines:
590 case PrimitiveMode::LineStrip:
591 case PrimitiveMode::LineLoop:
592 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
593 case PrimitiveMode::Triangles:
594 case PrimitiveMode::TriangleFan:
595 case PrimitiveMode::TriangleStrip:
596 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800597 default:
598 UNREACHABLE();
599 return false;
600 }
601}
602
Jamie Madill5b772312018-03-08 20:28:32 -0500603bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400604 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400605 GLsizei count,
606 GLenum type,
607 const GLvoid *indices,
608 GLsizei primcount)
609{
610 if (primcount < 0)
611 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700612 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400613 return false;
614 }
615
616 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
617 {
618 return false;
619 }
620
Jamie Madill9fdaa492018-02-16 10:52:11 -0500621 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400622}
623
624bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400625 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400626 GLint first,
627 GLsizei count,
628 GLsizei primcount)
629{
630 if (primcount < 0)
631 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700632 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400633 return false;
634 }
635
636 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
637 {
638 return false;
639 }
640
Jamie Madill9fdaa492018-02-16 10:52:11 -0500641 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400642}
643
Jamie Madill5b772312018-03-08 20:28:32 -0500644bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400645{
646 // Verify there is at least one active attribute with a divisor of zero
647 const State &state = context->getGLState();
648
649 Program *program = state.getProgram();
650
651 const auto &attribs = state.getVertexArray()->getVertexAttributes();
652 const auto &bindings = state.getVertexArray()->getVertexBindings();
653 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
654 {
655 const VertexAttribute &attrib = attribs[attributeIndex];
656 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300657 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400658 {
659 return true;
660 }
661 }
662
Brandon Jonesafa75152017-07-21 13:11:29 -0700663 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400664 return false;
665}
666
Jamie Madill5b772312018-03-08 20:28:32 -0500667bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500668{
669 switch (target)
670 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800671 case TextureType::_3D:
672 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800673 return true;
674 default:
675 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400676 }
677}
678
Jamie Madill5b772312018-03-08 20:28:32 -0500679bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800680{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800681 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800682 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800683 case TextureType::_2D:
684 case TextureType::_2DArray:
685 case TextureType::_2DMultisample:
686 case TextureType::CubeMap:
687 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800688 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800689 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400690 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800691 default:
692 return false;
693 }
694}
695
Jamie Madill5b772312018-03-08 20:28:32 -0500696bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500697{
He Yunchaoced53ae2016-11-29 15:00:51 +0800698 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
699 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400700 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500701
702 switch (target)
703 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800704 case GL_FRAMEBUFFER:
705 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400706
He Yunchaoced53ae2016-11-29 15:00:51 +0800707 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800708 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400709 return (context->getExtensions().framebufferBlit ||
710 context->getClientMajorVersion() >= 3);
711
He Yunchaoced53ae2016-11-29 15:00:51 +0800712 default:
713 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500714 }
715}
716
Jamie Madill5b772312018-03-08 20:28:32 -0500717bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400718{
Jamie Madillc29968b2016-01-20 11:17:23 -0500719 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400720 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800721 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400722 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800723 case TextureType::_2D:
724 case TextureType::_2DArray:
725 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500726 maxDimension = caps.max2DTextureSize;
727 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800728 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800729 maxDimension = caps.maxCubeMapTextureSize;
730 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800731 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400732 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800733 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800734 maxDimension = caps.max3DTextureSize;
735 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 default:
737 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400738 }
739
Jamie Madill43da7c42018-08-01 11:34:49 -0400740 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400741}
742
Jamie Madill5b772312018-03-08 20:28:32 -0500743bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800744 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700745 GLint level,
746 GLsizei width,
747 GLsizei height,
748 GLsizei depth,
749 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400750{
Brandon Jones6cad5662017-06-14 13:25:13 -0700751 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400752 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700753 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400754 return false;
755 }
Austin Kinross08528e12015-10-07 16:24:40 -0700756 // TexSubImage parameters can be NPOT without textureNPOT extension,
757 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500758 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500759 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500760 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400761 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400762 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700763 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400764 return false;
765 }
766
767 if (!ValidMipLevel(context, target, level))
768 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700769 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400770 return false;
771 }
772
773 return true;
774}
775
Geoff Lang966c9402017-04-18 12:38:27 -0400776bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
777{
778 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
779 (size % blockSize == 0);
780}
781
Jamie Madill5b772312018-03-08 20:28:32 -0500782bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500783 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400784 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500785 GLsizei width,
786 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400787{
Jamie Madill43da7c42018-08-01 11:34:49 -0400788 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400789 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400790 {
791 return false;
792 }
793
Geoff Lang966c9402017-04-18 12:38:27 -0400794 if (width < 0 || height < 0)
795 {
796 return false;
797 }
798
799 if (CompressedTextureFormatRequiresExactSize(internalFormat))
800 {
801 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
802 // block size for level 0 but WebGL disallows this.
803 bool smallerThanBlockSizeAllowed =
804 level > 0 || !context->getExtensions().webglCompatibility;
805
806 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
807 smallerThanBlockSizeAllowed) ||
808 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
809 smallerThanBlockSizeAllowed))
810 {
811 return false;
812 }
813 }
814
815 return true;
816}
817
Jamie Madill5b772312018-03-08 20:28:32 -0500818bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400819 GLenum internalFormat,
820 GLint xoffset,
821 GLint yoffset,
822 GLsizei width,
823 GLsizei height,
824 size_t textureWidth,
825 size_t textureHeight)
826{
Jamie Madill43da7c42018-08-01 11:34:49 -0400827 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400828 if (!formatInfo.compressed)
829 {
830 return false;
831 }
832
Geoff Lang44ff5a72017-02-03 15:15:43 -0500833 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400834 {
835 return false;
836 }
837
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500838 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400839 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500840 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400841 yoffset % formatInfo.compressedBlockHeight != 0)
842 {
843 return false;
844 }
845
846 // Allowed to either have data that is a multiple of block size or is smaller than the block
847 // size but fills the entire mip
848 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
849 static_cast<size_t>(width) == textureWidth &&
850 static_cast<size_t>(height) == textureHeight;
851 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
852 (height % formatInfo.compressedBlockHeight) == 0;
853 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400854 {
855 return false;
856 }
857 }
858
Geoff Langd4f180b2013-09-24 13:57:44 -0400859 return true;
860}
861
Jamie Madill5b772312018-03-08 20:28:32 -0500862bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800863 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400864 GLsizei width,
865 GLsizei height,
866 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400867 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400868 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400869 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400870 GLsizei imageSize)
871{
Jamie Madill43da7c42018-08-01 11:34:49 -0400872 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400873 if (pixelUnpackBuffer == nullptr && imageSize < 0)
874 {
875 // Checks are not required
876 return true;
877 }
878
879 // ...the data would be unpacked from the buffer object such that the memory reads required
880 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400881 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400882 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400883 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400884 const auto &unpack = context->getGLState().getUnpackState();
885
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800886 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400887 GLuint endByte = 0;
888 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400889 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400891 return false;
892 }
893
Geoff Langff5b2d52016-09-07 11:32:23 -0400894 if (pixelUnpackBuffer)
895 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400896 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400897 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
898 checkedEndByte += checkedOffset;
899
900 if (!checkedEndByte.IsValid() ||
901 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
902 {
903 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400905 return false;
906 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800907 if (context->getExtensions().webglCompatibility &&
908 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
909 {
910 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
911 PixelUnpackBufferBoundForTransformFeedback);
912 return false;
913 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400914 }
915 else
916 {
917 ASSERT(imageSize >= 0);
918 if (pixels == nullptr && imageSize != 0)
919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500920 context->handleError(InvalidOperation()
921 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400922 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400923 }
924
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400925 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500927 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400928 return false;
929 }
930 }
931
932 return true;
933}
934
Corentin Wallezad3ae902018-03-09 13:40:42 -0500935bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500936{
Geoff Lang37dde692014-01-31 16:34:54 -0500937 switch (queryType)
938 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500939 case QueryType::AnySamples:
940 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400941 return context->getClientMajorVersion() >= 3 ||
942 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500943 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800944 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500945 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800946 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500947 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800948 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500949 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800950 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800951 default:
952 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500953 }
954}
955
Jamie Madill5b772312018-03-08 20:28:32 -0500956bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400957 GLenum type,
958 GLboolean normalized,
959 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400960 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400961 bool pureInteger)
962{
963 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400964 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
965 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
966 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
967 // parameter exceeds 255.
968 constexpr GLsizei kMaxWebGLStride = 255;
969 if (stride > kMaxWebGLStride)
970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500971 context->handleError(InvalidValue()
972 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400973 return false;
974 }
975
976 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
977 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
978 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
979 // or an INVALID_OPERATION error is generated.
980 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
981 size_t typeSize = GetVertexFormatTypeSize(internalType);
982
983 ASSERT(isPow2(typeSize) && typeSize > 0);
984 size_t sizeMask = (typeSize - 1);
985 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
986 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400988 return false;
989 }
990
991 if ((stride & sizeMask) != 0)
992 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400994 return false;
995 }
996
997 return true;
998}
999
Jamie Madill5b772312018-03-08 20:28:32 -05001000Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001001{
He Yunchaoced53ae2016-11-29 15:00:51 +08001002 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1003 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1004 // or program object and INVALID_OPERATION if the provided name identifies an object
1005 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001006
Dian Xiang769769a2015-09-09 15:20:08 -07001007 Program *validProgram = context->getProgram(id);
1008
1009 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001010 {
Dian Xiang769769a2015-09-09 15:20:08 -07001011 if (context->getShader(id))
1012 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001013 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001014 }
1015 else
1016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001017 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001018 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001019 }
Dian Xiang769769a2015-09-09 15:20:08 -07001020
1021 return validProgram;
1022}
1023
Jamie Madill5b772312018-03-08 20:28:32 -05001024Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001025{
1026 // See ValidProgram for spec details.
1027
1028 Shader *validShader = context->getShader(id);
1029
1030 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001031 {
Dian Xiang769769a2015-09-09 15:20:08 -07001032 if (context->getProgram(id))
1033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001035 }
1036 else
1037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001038 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001039 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001040 }
Dian Xiang769769a2015-09-09 15:20:08 -07001041
1042 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001043}
1044
Jamie Madill43da7c42018-08-01 11:34:49 -04001045bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001046{
Geoff Langfa125c92017-10-24 13:01:46 -04001047 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001048 {
Geoff Langfa125c92017-10-24 13:01:46 -04001049 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1050 {
1051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1052 return false;
1053 }
Jamie Madillb4472272014-07-03 10:38:55 -04001054
Geoff Langfa125c92017-10-24 13:01:46 -04001055 // Color attachment 0 is validated below because it is always valid
1056 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001057 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001058 {
Geoff Langfa125c92017-10-24 13:01:46 -04001059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001060 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001061 }
1062 }
1063 else
1064 {
1065 switch (attachment)
1066 {
Geoff Langfa125c92017-10-24 13:01:46 -04001067 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001068 case GL_DEPTH_ATTACHMENT:
1069 case GL_STENCIL_ATTACHMENT:
1070 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001071
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 case GL_DEPTH_STENCIL_ATTACHMENT:
1073 if (!context->getExtensions().webglCompatibility &&
1074 context->getClientMajorVersion() < 3)
1075 {
Geoff Langfa125c92017-10-24 13:01:46 -04001076 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 return false;
1078 }
1079 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001080
He Yunchaoced53ae2016-11-29 15:00:51 +08001081 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001082 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001084 }
1085 }
1086
1087 return true;
1088}
1089
Jamie Madill5b772312018-03-08 20:28:32 -05001090bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 GLenum target,
1092 GLsizei samples,
1093 GLenum internalformat,
1094 GLsizei width,
1095 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096{
1097 switch (target)
1098 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001099 case GL_RENDERBUFFER:
1100 break;
1101 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001103 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 }
1105
1106 if (width < 0 || height < 0 || samples < 0)
1107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001108 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001109 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 }
1111
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001112 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1113 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1114
1115 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001116 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001118 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001119 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001120 }
1121
1122 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1123 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001124 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001125 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001126 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001129 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001130 }
1131
Geoff Langaae65a42014-05-26 12:43:44 -04001132 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001134 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001135 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001136 }
1137
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001138 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139 if (handle == 0)
1140 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001142 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001143 }
1144
1145 return true;
1146}
1147
Jamie Madill43da7c42018-08-01 11:34:49 -04001148bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001149 GLenum target,
1150 GLenum attachment,
1151 GLenum renderbuffertarget,
1152 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001153{
Geoff Lange8afa902017-09-27 15:00:43 -04001154 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001156 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001158 }
1159
Jamie Madill43da7c42018-08-01 11:34:49 -04001160 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001161
Jamie Madill84115c92015-04-23 15:00:07 -04001162 ASSERT(framebuffer);
1163 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001167 }
1168
Jamie Madillb4472272014-07-03 10:38:55 -04001169 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001170 {
Jamie Madillb4472272014-07-03 10:38:55 -04001171 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001172 }
1173
Jamie Madillab9d82c2014-01-21 16:38:14 -05001174 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1175 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1176 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1177 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1178 if (renderbuffer != 0)
1179 {
1180 if (!context->getRenderbuffer(renderbuffer))
1181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001183 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001184 }
1185 }
1186
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001187 return true;
1188}
1189
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001190bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001191 GLint srcX0,
1192 GLint srcY0,
1193 GLint srcX1,
1194 GLint srcY1,
1195 GLint dstX0,
1196 GLint dstY0,
1197 GLint dstX1,
1198 GLint dstY1,
1199 GLbitfield mask,
1200 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001201{
1202 switch (filter)
1203 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001204 case GL_NEAREST:
1205 break;
1206 case GL_LINEAR:
1207 break;
1208 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001209 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001211 }
1212
1213 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001215 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001216 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001217 }
1218
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001219 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1220 // color buffer, leaving only nearest being unfiltered from above
1221 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001223 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001225 }
1226
Jamie Madill51f40ec2016-06-15 14:06:00 -04001227 const auto &glState = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04001228 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1229 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001230
1231 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001233 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001234 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001235 }
1236
Jamie Madill427064d2018-04-13 16:20:34 -04001237 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001238 {
Jamie Madill48faf802014-11-06 15:27:22 -05001239 return false;
1240 }
1241
Jamie Madill427064d2018-04-13 16:20:34 -04001242 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001243 {
Jamie Madill48faf802014-11-06 15:27:22 -05001244 return false;
1245 }
1246
Qin Jiajiaaef92162018-02-27 13:51:44 +08001247 if (readFramebuffer->id() == drawFramebuffer->id())
1248 {
1249 context->handleError(InvalidOperation());
1250 return false;
1251 }
1252
Jamie Madille98b1b52018-03-08 09:47:23 -05001253 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 {
Geoff Langb1196682014-07-23 13:47:29 -04001255 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 }
1257
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001258 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1259 // always run it in order to avoid triggering driver bugs.
1260 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1261 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001262 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001263 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1264 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001265 }
1266
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001267 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1268
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 if (mask & GL_COLOR_BUFFER_BIT)
1270 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001271 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001272 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001273
He Yunchao66a41a22016-12-15 16:45:05 +08001274 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001276 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277
Geoff Langa15472a2015-08-11 11:48:03 -04001278 for (size_t drawbufferIdx = 0;
1279 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280 {
Geoff Langa15472a2015-08-11 11:48:03 -04001281 const FramebufferAttachment *attachment =
1282 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1283 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001284 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001285 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001286
Geoff Langb2f3d052013-08-13 12:49:27 -04001287 // The GL ES 3.0.2 spec (pg 193) states that:
1288 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001289 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1290 // as well
1291 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1292 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001293 // Changes with EXT_color_buffer_float:
1294 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001295 GLenum readComponentType = readFormat.info->componentType;
1296 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001297 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001298 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001299 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001300 drawComponentType == GL_SIGNED_NORMALIZED);
1301
1302 if (extensions.colorBufferFloat)
1303 {
1304 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1305 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1306
1307 if (readFixedOrFloat != drawFixedOrFloat)
1308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001309 context->handleError(InvalidOperation()
1310 << "If the read buffer contains fixed-point or "
1311 "floating-point values, the draw buffer must "
1312 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001313 return false;
1314 }
1315 }
1316 else if (readFixedPoint != drawFixedPoint)
1317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidOperation()
1319 << "If the read buffer contains fixed-point values, "
1320 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001321 return false;
1322 }
1323
1324 if (readComponentType == GL_UNSIGNED_INT &&
1325 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001328 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329 }
1330
Jamie Madill6163c752015-12-07 16:32:59 -05001331 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001333 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001334 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 }
1336
Jamie Madilla3944d42016-07-22 22:13:26 -04001337 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001338 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001340 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001341 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001342 }
Geoff Lange4915782017-04-12 15:19:07 -04001343
1344 if (context->getExtensions().webglCompatibility &&
1345 *readColorBuffer == *attachment)
1346 {
1347 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001348 InvalidOperation()
1349 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001350 return false;
1351 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 }
1353 }
1354
Jamie Madilla3944d42016-07-22 22:13:26 -04001355 if ((readFormat.info->componentType == GL_INT ||
1356 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1357 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001360 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 }
He Yunchao66a41a22016-12-15 16:45:05 +08001363 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1364 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1365 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1366 // situation is an application error that would lead to a crash in ANGLE.
1367 else if (drawFramebuffer->hasEnabledDrawBuffer())
1368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001369 context->handleError(
1370 InvalidOperation()
1371 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001372 return false;
1373 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001374 }
1375
He Yunchaoced53ae2016-11-29 15:00:51 +08001376 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001377 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1378 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001380 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001382 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001383 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001384 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001385 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001387 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 {
Kenneth Russell69382852017-07-21 16:38:44 -04001389 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001391 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001392 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001395 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001398 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 }
Geoff Lange4915782017-04-12 15:19:07 -04001400
1401 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 context->handleError(
1404 InvalidOperation()
1405 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001406 return false;
1407 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 }
He Yunchao66a41a22016-12-15 16:45:05 +08001409 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1410 else if (drawBuffer)
1411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1413 "depth/stencil attachment of a "
1414 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001415 return false;
1416 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 }
1418 }
1419
Martin Radeva3ed4572017-07-27 18:29:37 +03001420 // ANGLE_multiview, Revision 1:
1421 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001422 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1423 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1424 // views in the current read framebuffer is more than one.
1425 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001426 {
1427 context->handleError(InvalidFramebufferOperation()
1428 << "Attempt to read from a multi-view framebuffer.");
1429 return false;
1430 }
1431 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1432 {
1433 context->handleError(InvalidFramebufferOperation()
1434 << "Attempt to write to a multi-view framebuffer.");
1435 return false;
1436 }
1437
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001438 return true;
1439}
1440
Jamie Madill4928b7c2017-06-20 12:57:39 -04001441bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001442 GLint x,
1443 GLint y,
1444 GLsizei width,
1445 GLsizei height,
1446 GLenum format,
1447 GLenum type,
1448 GLsizei bufSize,
1449 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001450 GLsizei *columns,
1451 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001452 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001453{
1454 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001455 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001456 return false;
1457 }
1458
Brandon Jonesd1049182018-03-28 10:02:20 -07001459 GLsizei writeLength = 0;
1460 GLsizei writeColumns = 0;
1461 GLsizei writeRows = 0;
1462
1463 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1464 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001465 {
Geoff Langb1196682014-07-23 13:47:29 -04001466 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001467 }
1468
Brandon Jonesd1049182018-03-28 10:02:20 -07001469 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001470 {
Geoff Langb1196682014-07-23 13:47:29 -04001471 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001472 }
1473
Brandon Jonesd1049182018-03-28 10:02:20 -07001474 SetRobustLengthParam(length, writeLength);
1475 SetRobustLengthParam(columns, writeColumns);
1476 SetRobustLengthParam(rows, writeRows);
1477
Jamie Madillc29968b2016-01-20 11:17:23 -05001478 return true;
1479}
1480
1481bool ValidateReadnPixelsEXT(Context *context,
1482 GLint x,
1483 GLint y,
1484 GLsizei width,
1485 GLsizei height,
1486 GLenum format,
1487 GLenum type,
1488 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001489 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001490{
1491 if (bufSize < 0)
1492 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001493 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001494 return false;
1495 }
1496
Geoff Lang62fce5b2016-09-30 10:46:35 -04001497 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001498 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001499}
Jamie Madill26e91952014-03-05 15:01:27 -05001500
Jamie Madill4928b7c2017-06-20 12:57:39 -04001501bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001502 GLint x,
1503 GLint y,
1504 GLsizei width,
1505 GLsizei height,
1506 GLenum format,
1507 GLenum type,
1508 GLsizei bufSize,
1509 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001510 GLsizei *columns,
1511 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001512 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001513{
Brandon Jonesd1049182018-03-28 10:02:20 -07001514 GLsizei writeLength = 0;
1515 GLsizei writeColumns = 0;
1516 GLsizei writeRows = 0;
1517
Geoff Lang62fce5b2016-09-30 10:46:35 -04001518 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001519 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001520 return false;
1521 }
1522
Brandon Jonesd1049182018-03-28 10:02:20 -07001523 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1524 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001525 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001526 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001527 }
1528
Brandon Jonesd1049182018-03-28 10:02:20 -07001529 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001530 {
1531 return false;
1532 }
1533
Brandon Jonesd1049182018-03-28 10:02:20 -07001534 SetRobustLengthParam(length, writeLength);
1535 SetRobustLengthParam(columns, writeColumns);
1536 SetRobustLengthParam(rows, writeRows);
1537
Geoff Lang62fce5b2016-09-30 10:46:35 -04001538 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001539}
1540
Jamie Madill43da7c42018-08-01 11:34:49 -04001541bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001542{
1543 if (!context->getExtensions().occlusionQueryBoolean &&
1544 !context->getExtensions().disjointTimerQuery)
1545 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001546 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001547 return false;
1548 }
1549
Olli Etuaho41997e72016-03-10 13:38:39 +02001550 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001551}
1552
Jamie Madill43da7c42018-08-01 11:34:49 -04001553bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001554{
1555 if (!context->getExtensions().occlusionQueryBoolean &&
1556 !context->getExtensions().disjointTimerQuery)
1557 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001559 return false;
1560 }
1561
Olli Etuaho41997e72016-03-10 13:38:39 +02001562 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001563}
1564
Jamie Madill43da7c42018-08-01 11:34:49 -04001565bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001566{
1567 if (!context->getExtensions().occlusionQueryBoolean &&
1568 !context->getExtensions().disjointTimerQuery)
1569 {
1570 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1571 return false;
1572 }
1573
1574 return true;
1575}
1576
Jamie Madill43da7c42018-08-01 11:34:49 -04001577bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001578{
1579 if (!ValidQueryType(context, target))
1580 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001581 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001582 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001583 }
1584
1585 if (id == 0)
1586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001587 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001588 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001589 }
1590
1591 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1592 // of zero, if the active query object name for <target> is non-zero (for the
1593 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1594 // the active query for either target is non-zero), if <id> is the name of an
1595 // existing query object whose type does not match <target>, or if <id> is the
1596 // active query object name for any query type, the error INVALID_OPERATION is
1597 // generated.
1598
1599 // Ensure no other queries are active
1600 // NOTE: If other queries than occlusion are supported, we will need to check
1601 // separately that:
1602 // a) The query ID passed is not the current active query for any target/type
1603 // b) There are no active queries for the requested target (and in the case
1604 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1605 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001606
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001607 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001609 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001610 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001611 }
1612
1613 Query *queryObject = context->getQuery(id, true, target);
1614
1615 // check that name was obtained with glGenQueries
1616 if (!queryObject)
1617 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001618 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001619 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001620 }
1621
1622 // check for type mismatch
1623 if (queryObject->getType() != target)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001627 }
1628
1629 return true;
1630}
1631
Jamie Madill43da7c42018-08-01 11:34:49 -04001632bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001633{
1634 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001635 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001636 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001637 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001638 return false;
1639 }
1640
1641 return ValidateBeginQueryBase(context, target, id);
1642}
1643
Jamie Madill43da7c42018-08-01 11:34:49 -04001644bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001645{
1646 if (!ValidQueryType(context, target))
1647 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001648 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001649 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001650 }
1651
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001652 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001653
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001656 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001657 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001658 }
1659
Jamie Madill45c785d2014-05-13 14:09:34 -04001660 return true;
1661}
1662
Jamie Madill43da7c42018-08-01 11:34:49 -04001663bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001664{
1665 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001666 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001669 return false;
1670 }
1671
1672 return ValidateEndQueryBase(context, target);
1673}
1674
Corentin Wallezad3ae902018-03-09 13:40:42 -05001675bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001676{
1677 if (!context->getExtensions().disjointTimerQuery)
1678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001679 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001680 return false;
1681 }
1682
Corentin Wallezad3ae902018-03-09 13:40:42 -05001683 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001685 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001686 return false;
1687 }
1688
1689 Query *queryObject = context->getQuery(id, true, target);
1690 if (queryObject == nullptr)
1691 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001693 return false;
1694 }
1695
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001696 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001699 return false;
1700 }
1701
1702 return true;
1703}
1704
Corentin Wallezad3ae902018-03-09 13:40:42 -05001705bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001706{
Geoff Lang2186c382016-10-14 10:54:54 -04001707 if (numParams)
1708 {
1709 *numParams = 0;
1710 }
1711
Corentin Wallezad3ae902018-03-09 13:40:42 -05001712 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001714 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715 return false;
1716 }
1717
1718 switch (pname)
1719 {
1720 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001721 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001724 return false;
1725 }
1726 break;
1727 case GL_QUERY_COUNTER_BITS_EXT:
1728 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001729 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001730 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001731 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 return false;
1733 }
1734 break;
1735 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001736 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 return false;
1738 }
1739
Geoff Lang2186c382016-10-14 10:54:54 -04001740 if (numParams)
1741 {
1742 // All queries return only one value
1743 *numParams = 1;
1744 }
1745
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 return true;
1747}
1748
Corentin Wallezad3ae902018-03-09 13:40:42 -05001749bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750{
1751 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001752 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001754 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001755 return false;
1756 }
1757
Geoff Lang2186c382016-10-14 10:54:54 -04001758 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759}
1760
Geoff Lang2186c382016-10-14 10:54:54 -04001761bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001762 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001763 GLenum pname,
1764 GLsizei bufSize,
1765 GLsizei *length,
1766 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767{
Geoff Lang2186c382016-10-14 10:54:54 -04001768 if (!ValidateRobustEntryPoint(context, bufSize))
1769 {
1770 return false;
1771 }
1772
Brandon Jonesd1049182018-03-28 10:02:20 -07001773 GLsizei numParams = 0;
1774
1775 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001776 {
1777 return false;
1778 }
1779
Brandon Jonesd1049182018-03-28 10:02:20 -07001780 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001781 {
1782 return false;
1783 }
1784
Brandon Jonesd1049182018-03-28 10:02:20 -07001785 SetRobustLengthParam(length, numParams);
1786
Geoff Lang2186c382016-10-14 10:54:54 -04001787 return true;
1788}
1789
1790bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1791{
1792 if (numParams)
1793 {
1794 *numParams = 0;
1795 }
1796
Corentin Wallezad3ae902018-03-09 13:40:42 -05001797 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001798
1799 if (!queryObject)
1800 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001801 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802 return false;
1803 }
1804
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001805 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001806 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001808 return false;
1809 }
1810
1811 switch (pname)
1812 {
1813 case GL_QUERY_RESULT_EXT:
1814 case GL_QUERY_RESULT_AVAILABLE_EXT:
1815 break;
1816
1817 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001818 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819 return false;
1820 }
1821
Geoff Lang2186c382016-10-14 10:54:54 -04001822 if (numParams)
1823 {
1824 *numParams = 1;
1825 }
1826
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827 return true;
1828}
1829
1830bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1831{
1832 if (!context->getExtensions().disjointTimerQuery)
1833 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001834 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001835 return false;
1836 }
Geoff Lang2186c382016-10-14 10:54:54 -04001837 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1838}
1839
1840bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1841 GLuint id,
1842 GLenum pname,
1843 GLsizei bufSize,
1844 GLsizei *length,
1845 GLint *params)
1846{
1847 if (!context->getExtensions().disjointTimerQuery)
1848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001849 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001850 return false;
1851 }
1852
1853 if (!ValidateRobustEntryPoint(context, bufSize))
1854 {
1855 return false;
1856 }
1857
Brandon Jonesd1049182018-03-28 10:02:20 -07001858 GLsizei numParams = 0;
1859
1860 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001861 {
1862 return false;
1863 }
1864
Brandon Jonesd1049182018-03-28 10:02:20 -07001865 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001866 {
1867 return false;
1868 }
1869
Brandon Jonesd1049182018-03-28 10:02:20 -07001870 SetRobustLengthParam(length, numParams);
1871
Geoff Lang2186c382016-10-14 10:54:54 -04001872 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873}
1874
1875bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1876{
1877 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001878 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001879 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001880 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001881 return false;
1882 }
Geoff Lang2186c382016-10-14 10:54:54 -04001883 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1884}
1885
1886bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1887 GLuint id,
1888 GLenum pname,
1889 GLsizei bufSize,
1890 GLsizei *length,
1891 GLuint *params)
1892{
1893 if (!context->getExtensions().disjointTimerQuery &&
1894 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1895 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001896 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001897 return false;
1898 }
1899
1900 if (!ValidateRobustEntryPoint(context, bufSize))
1901 {
1902 return false;
1903 }
1904
Brandon Jonesd1049182018-03-28 10:02:20 -07001905 GLsizei numParams = 0;
1906
1907 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001908 {
1909 return false;
1910 }
1911
Brandon Jonesd1049182018-03-28 10:02:20 -07001912 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001913 {
1914 return false;
1915 }
1916
Brandon Jonesd1049182018-03-28 10:02:20 -07001917 SetRobustLengthParam(length, numParams);
1918
Geoff Lang2186c382016-10-14 10:54:54 -04001919 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001920}
1921
1922bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1923{
1924 if (!context->getExtensions().disjointTimerQuery)
1925 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001926 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001927 return false;
1928 }
Geoff Lang2186c382016-10-14 10:54:54 -04001929 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1930}
1931
1932bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1933 GLuint id,
1934 GLenum pname,
1935 GLsizei bufSize,
1936 GLsizei *length,
1937 GLint64 *params)
1938{
1939 if (!context->getExtensions().disjointTimerQuery)
1940 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001941 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001942 return false;
1943 }
1944
1945 if (!ValidateRobustEntryPoint(context, bufSize))
1946 {
1947 return false;
1948 }
1949
Brandon Jonesd1049182018-03-28 10:02:20 -07001950 GLsizei numParams = 0;
1951
1952 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001953 {
1954 return false;
1955 }
1956
Brandon Jonesd1049182018-03-28 10:02:20 -07001957 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001958 {
1959 return false;
1960 }
1961
Brandon Jonesd1049182018-03-28 10:02:20 -07001962 SetRobustLengthParam(length, numParams);
1963
Geoff Lang2186c382016-10-14 10:54:54 -04001964 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001965}
1966
1967bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1968{
1969 if (!context->getExtensions().disjointTimerQuery)
1970 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001971 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001972 return false;
1973 }
Geoff Lang2186c382016-10-14 10:54:54 -04001974 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1975}
1976
1977bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1978 GLuint id,
1979 GLenum pname,
1980 GLsizei bufSize,
1981 GLsizei *length,
1982 GLuint64 *params)
1983{
1984 if (!context->getExtensions().disjointTimerQuery)
1985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001986 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001987 return false;
1988 }
1989
1990 if (!ValidateRobustEntryPoint(context, bufSize))
1991 {
1992 return false;
1993 }
1994
Brandon Jonesd1049182018-03-28 10:02:20 -07001995 GLsizei numParams = 0;
1996
1997 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001998 {
1999 return false;
2000 }
2001
Brandon Jonesd1049182018-03-28 10:02:20 -07002002 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002003 {
2004 return false;
2005 }
2006
Brandon Jonesd1049182018-03-28 10:02:20 -07002007 SetRobustLengthParam(length, numParams);
2008
Geoff Lang2186c382016-10-14 10:54:54 -04002009 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010}
2011
Jamie Madill5b772312018-03-08 20:28:32 -05002012bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002013 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002014 GLint location,
2015 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002016 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002017{
Jiajia Qin5451d532017-11-16 17:16:34 +08002018 // TODO(Jiajia): Add image uniform check in future.
2019 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002020 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002021 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002022 return false;
2023 }
2024
Jiajia Qin5451d532017-11-16 17:16:34 +08002025 if (!program)
2026 {
2027 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2028 return false;
2029 }
2030
2031 if (!program->isLinked())
2032 {
2033 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2034 return false;
2035 }
2036
2037 if (location == -1)
2038 {
2039 // Silently ignore the uniform command
2040 return false;
2041 }
2042
2043 const auto &uniformLocations = program->getUniformLocations();
2044 size_t castedLocation = static_cast<size_t>(location);
2045 if (castedLocation >= uniformLocations.size())
2046 {
2047 context->handleError(InvalidOperation() << "Invalid uniform location");
2048 return false;
2049 }
2050
2051 const auto &uniformLocation = uniformLocations[castedLocation];
2052 if (uniformLocation.ignored)
2053 {
2054 // Silently ignore the uniform command
2055 return false;
2056 }
2057
2058 if (!uniformLocation.used())
2059 {
2060 context->handleError(InvalidOperation());
2061 return false;
2062 }
2063
2064 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2065
2066 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002067 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002068 {
2069 context->handleError(InvalidOperation());
2070 return false;
2071 }
2072
2073 *uniformOut = &uniform;
2074 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002075}
2076
Jamie Madill5b772312018-03-08 20:28:32 -05002077bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002078 GLenum uniformType,
2079 GLsizei count,
2080 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002081{
Jiajia Qin5451d532017-11-16 17:16:34 +08002082 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2083 // It is compatible with INT or BOOL.
2084 // Do these cheap tests first, for a little extra speed.
2085 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002086 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002087 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002088 }
2089
Jiajia Qin5451d532017-11-16 17:16:34 +08002090 if (IsSamplerType(uniformType))
2091 {
2092 // Check that the values are in range.
2093 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2094 for (GLsizei i = 0; i < count; ++i)
2095 {
2096 if (value[i] < 0 || value[i] >= max)
2097 {
2098 context->handleError(InvalidValue() << "sampler uniform value out of range");
2099 return false;
2100 }
2101 }
2102 return true;
2103 }
2104
2105 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2106 return false;
2107}
2108
Jamie Madill5b772312018-03-08 20:28:32 -05002109bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002110{
2111 // Check that the value type is compatible with uniform type.
2112 // Do the cheaper test first, for a little extra speed.
2113 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2114 {
2115 return true;
2116 }
2117
2118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2119 return false;
2120}
2121
Jamie Madill5b772312018-03-08 20:28:32 -05002122bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002123{
2124 // Check that the value type is compatible with uniform type.
2125 if (valueType == uniformType)
2126 {
2127 return true;
2128 }
2129
2130 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2131 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002132}
2133
Jamie Madill5b772312018-03-08 20:28:32 -05002134bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002135{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002136 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002137 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002138 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2139 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002140}
2141
Jamie Madill5b772312018-03-08 20:28:32 -05002142bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002143{
2144 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002145 Program *programObject = context->getGLState().getProgram();
Frank Henigmana98a6472017-02-02 21:38:32 -05002146 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2147 ValidateUniform1ivValue(context, uniform->type, count, value);
2148}
2149
Jamie Madill5b772312018-03-08 20:28:32 -05002150bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002151 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002152 GLint location,
2153 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002154 GLboolean transpose)
2155{
Geoff Lang92019432017-11-20 13:09:34 -05002156 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002158 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002159 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002160 }
2161
Jamie Madill62d31cb2015-09-11 13:25:51 -04002162 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002163 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002164 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2165 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002166}
2167
Jamie Madill5b772312018-03-08 20:28:32 -05002168bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002169{
2170 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002172 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002173 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002174 }
2175
Jamie Madill0af26e12015-03-05 19:54:33 -05002176 const Caps &caps = context->getCaps();
2177
Jamie Madill893ab082014-05-16 16:56:10 -04002178 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2179 {
2180 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2181
Jamie Madill0af26e12015-03-05 19:54:33 -05002182 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002184 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002185 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002186 }
2187 }
2188
2189 switch (pname)
2190 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002191 case GL_TEXTURE_BINDING_2D:
2192 case GL_TEXTURE_BINDING_CUBE_MAP:
2193 case GL_TEXTURE_BINDING_3D:
2194 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002195 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002196 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002197 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2198 if (!context->getExtensions().textureRectangle)
2199 {
2200 context->handleError(InvalidEnum()
2201 << "ANGLE_texture_rectangle extension not present");
2202 return false;
2203 }
2204 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002205 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2206 if (!context->getExtensions().eglStreamConsumerExternal &&
2207 !context->getExtensions().eglImageExternal)
2208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002209 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2210 "nor GL_OES_EGL_image_external "
2211 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002212 return false;
2213 }
2214 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002215
He Yunchaoced53ae2016-11-29 15:00:51 +08002216 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2217 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002218 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002219 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2220 ASSERT(readFramebuffer);
2221
Jamie Madill427064d2018-04-13 16:20:34 -04002222 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002223 {
Geoff Langb1196682014-07-23 13:47:29 -04002224 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002225 }
2226
Jamie Madille98b1b52018-03-08 09:47:23 -05002227 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002228 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002229 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002230 return false;
2231 }
2232
Jamie Madille98b1b52018-03-08 09:47:23 -05002233 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002234 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002236 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002237 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002238 }
2239 }
2240 break;
2241
He Yunchaoced53ae2016-11-29 15:00:51 +08002242 default:
2243 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002244 }
2245
2246 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002247 if (*numParams == 0)
2248 {
2249 return false;
2250 }
2251
2252 return true;
2253}
2254
Brandon Jonesd1049182018-03-28 10:02:20 -07002255bool ValidateGetBooleanvRobustANGLE(Context *context,
2256 GLenum pname,
2257 GLsizei bufSize,
2258 GLsizei *length,
2259 GLboolean *params)
2260{
2261 GLenum nativeType;
2262 unsigned int numParams = 0;
2263
2264 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2265 {
2266 return false;
2267 }
2268
2269 SetRobustLengthParam(length, numParams);
2270
2271 return true;
2272}
2273
2274bool ValidateGetFloatvRobustANGLE(Context *context,
2275 GLenum pname,
2276 GLsizei bufSize,
2277 GLsizei *length,
2278 GLfloat *params)
2279{
2280 GLenum nativeType;
2281 unsigned int numParams = 0;
2282
2283 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2284 {
2285 return false;
2286 }
2287
2288 SetRobustLengthParam(length, numParams);
2289
2290 return true;
2291}
2292
2293bool ValidateGetIntegervRobustANGLE(Context *context,
2294 GLenum pname,
2295 GLsizei bufSize,
2296 GLsizei *length,
2297 GLint *data)
2298{
2299 GLenum nativeType;
2300 unsigned int numParams = 0;
2301
2302 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2303 {
2304 return false;
2305 }
2306
2307 SetRobustLengthParam(length, numParams);
2308
2309 return true;
2310}
2311
2312bool ValidateGetInteger64vRobustANGLE(Context *context,
2313 GLenum pname,
2314 GLsizei bufSize,
2315 GLsizei *length,
2316 GLint64 *data)
2317{
2318 GLenum nativeType;
2319 unsigned int numParams = 0;
2320
2321 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2322 {
2323 return false;
2324 }
2325
2326 if (nativeType == GL_INT_64_ANGLEX)
2327 {
2328 CastStateValues(context, nativeType, pname, numParams, data);
2329 return false;
2330 }
2331
2332 SetRobustLengthParam(length, numParams);
2333 return true;
2334}
2335
Jamie Madill5b772312018-03-08 20:28:32 -05002336bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002337 GLenum pname,
2338 GLsizei bufSize,
2339 GLenum *nativeType,
2340 unsigned int *numParams)
2341{
2342 if (!ValidateRobustEntryPoint(context, bufSize))
2343 {
2344 return false;
2345 }
2346
2347 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2348 {
2349 return false;
2350 }
2351
2352 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002353 {
2354 return false;
2355 }
2356
2357 return true;
2358}
2359
Jamie Madill5b772312018-03-08 20:28:32 -05002360bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002361 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002362 GLint level,
2363 GLenum internalformat,
2364 bool isSubImage,
2365 GLint xoffset,
2366 GLint yoffset,
2367 GLint zoffset,
2368 GLint x,
2369 GLint y,
2370 GLsizei width,
2371 GLsizei height,
2372 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002373 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002374{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002375 TextureType texType = TextureTargetToType(target);
2376
Brandon Jones6cad5662017-06-14 13:25:13 -07002377 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002378 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002379 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2380 return false;
2381 }
2382
2383 if (width < 0 || height < 0)
2384 {
2385 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002386 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002387 }
2388
He Yunchaoced53ae2016-11-29 15:00:51 +08002389 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2390 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002392 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002393 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002394 }
2395
2396 if (border != 0)
2397 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002398 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002399 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002400 }
2401
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002402 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002403 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002404 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002405 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002406 }
2407
Jamie Madill43da7c42018-08-01 11:34:49 -04002408 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002409 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002410 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002411 {
Geoff Langb1196682014-07-23 13:47:29 -04002412 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002413 }
2414
Jamie Madille98b1b52018-03-08 09:47:23 -05002415 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002416 {
Geoff Langb1196682014-07-23 13:47:29 -04002417 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002418 }
2419
Martin Radev138064f2016-07-15 12:03:41 +03002420 if (readFramebuffer->getReadBufferState() == GL_NONE)
2421 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002422 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002423 return false;
2424 }
2425
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002426 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2427 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002428 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002429 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002430 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2431 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002434 return false;
2435 }
2436
Martin Radev04e2c3b2017-07-27 16:54:35 +03002437 // ANGLE_multiview spec, Revision 1:
2438 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2439 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002440 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2441 // framebuffer is more than one.
2442 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002443 {
2444 context->handleError(InvalidFramebufferOperation()
2445 << "The active read framebuffer object has multiview attachments.");
2446 return false;
2447 }
2448
Jamie Madill43da7c42018-08-01 11:34:49 -04002449 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002450
Geoff Langaae65a42014-05-26 12:43:44 -04002451 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002452 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002453 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002454 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002455 maxDimension = caps.max2DTextureSize;
2456 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002457
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002458 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002459 maxDimension = caps.maxCubeMapTextureSize;
2460 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002461
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002462 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002463 maxDimension = caps.maxRectangleTextureSize;
2464 break;
2465
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002466 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002467 maxDimension = caps.max2DTextureSize;
2468 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002469
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002470 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002471 maxDimension = caps.max3DTextureSize;
2472 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002473
He Yunchaoced53ae2016-11-29 15:00:51 +08002474 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002475 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002476 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002477 }
2478
Jamie Madill43da7c42018-08-01 11:34:49 -04002479 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002480 if (!texture)
2481 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002482 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002483 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002484 }
2485
Geoff Lang69cce582015-09-17 13:20:36 -04002486 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002488 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002489 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 }
2491
Jamie Madill43da7c42018-08-01 11:34:49 -04002492 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002493 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002494 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002495
Geoff Lang966c9402017-04-18 12:38:27 -04002496 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002498 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002499 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002500 }
2501
2502 if (isSubImage)
2503 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002504 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2505 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2506 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002508 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002509 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002510 }
2511 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002512 else
2513 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002514 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002515 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002516 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002517 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002518 }
2519
Geoff Langeb66a6e2016-10-31 13:06:12 -04002520 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002521 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002524 }
2525
2526 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002527 if (static_cast<int>(width) > maxLevelDimension ||
2528 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002529 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002530 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002531 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002532 }
2533 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002534
Jamie Madill0c8abca2016-07-22 20:21:26 -04002535 if (textureFormatOut)
2536 {
2537 *textureFormatOut = texture->getFormat(target, level);
2538 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002539
2540 // Detect texture copying feedback loops for WebGL.
2541 if (context->getExtensions().webglCompatibility)
2542 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002543 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002544 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002545 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002546 return false;
2547 }
2548 }
2549
Jamie Madill560a8d82014-05-21 13:06:20 -04002550 return true;
2551}
2552
Jamie Madille7d80f32018-08-08 15:49:23 -04002553ErrorAndMessage ValidateDrawStates(Context *context)
2554{
2555 const Extensions &extensions = context->getExtensions();
2556 const State &state = context->getGLState();
2557
2558 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2559 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2560 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2561 if (!extensions.webglCompatibility && state.getVertexArray()->hasMappedEnabledArrayBuffer())
2562 {
2563 return {GL_INVALID_OPERATION, nullptr};
2564 }
2565
2566 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2567 // Section 6.10 of the WebGL 1.0 spec.
2568 Framebuffer *framebuffer = state.getDrawFramebuffer();
2569 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2570 {
2571 ASSERT(framebuffer);
2572 const FramebufferAttachment *dsAttachment =
2573 framebuffer->getStencilOrDepthStencilAttachment();
2574 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2575 ASSERT(stencilBits <= 8);
2576
2577 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2578 if (depthStencilState.stencilTest && stencilBits > 0)
2579 {
2580 GLuint maxStencilValue = (1 << stencilBits) - 1;
2581
2582 bool differentRefs =
2583 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2584 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2585 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2586 (depthStencilState.stencilBackWritemask & maxStencilValue);
2587 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2588 (depthStencilState.stencilBackMask & maxStencilValue);
2589
2590 if (differentRefs || differentWritemasks || differentMasks)
2591 {
2592 if (!extensions.webglCompatibility)
2593 {
2594 WARN() << "This ANGLE implementation does not support separate front/back "
2595 "stencil writemasks, reference values, or stencil mask values.";
2596 }
2597 return {GL_INVALID_OPERATION, kErrorStencilReferenceMaskOrMismatch};
2598 }
2599 }
2600 }
2601
2602 if (!framebuffer->isComplete(context))
2603 {
2604 return {GL_INVALID_FRAMEBUFFER_OPERATION, nullptr};
2605 }
2606
2607 if (context->getStateCache().hasAnyEnabledClientAttrib())
2608 {
2609 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2610 {
2611 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2612 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2613 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2614 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
2615 return {GL_INVALID_OPERATION, kErrorVertexArrayNoBuffer};
2616 }
2617
2618 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2619 {
2620 // This is an application error that would normally result in a crash, but we catch it
2621 // and return an error
2622 return {GL_INVALID_OPERATION, kErrorVertexArrayNoBufferPointer};
2623 }
2624 }
2625
2626 // If we are running GLES1, there is no current program.
2627 if (context->getClientVersion() >= Version(2, 0))
2628 {
2629 Program *program = state.getProgram();
2630 if (!program)
2631 {
2632 return {GL_INVALID_OPERATION, kErrorProgramNotBound};
2633 }
2634
2635 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2636 // vertex shader stage or fragment shader stage is a undefined behaviour.
2637 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2638 // produce undefined result.
2639 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2640 !program->hasLinkedShaderStage(ShaderType::Fragment))
2641 {
2642 return {GL_INVALID_OPERATION, kErrorNoActiveGraphicsShaderStage};
2643 }
2644
2645 if (!program->validateSamplers(nullptr, context->getCaps()))
2646 {
2647 return {GL_INVALID_OPERATION, nullptr};
2648 }
2649
2650 if (extensions.multiview)
2651 {
2652 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2653 const int framebufferNumViews = framebuffer->getNumViews();
2654 if (framebufferNumViews != programNumViews)
2655 {
2656 return {GL_INVALID_OPERATION, kErrorMultiviewMismatch};
2657 }
2658
2659 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2660 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2661 framebufferNumViews > 1)
2662 {
2663 return {GL_INVALID_OPERATION, kErrorMultiviewTransformFeedback};
2664 }
2665
2666 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2667 state.isQueryActive(QueryType::TimeElapsed))
2668 {
2669 return {GL_INVALID_OPERATION, kErrorMultiviewTimerQuery};
2670 }
2671 }
2672
2673 // Uniform buffer validation
2674 for (unsigned int uniformBlockIndex = 0;
2675 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2676 {
2677 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
2678 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2679 const OffsetBindingPointer<Buffer> &uniformBuffer =
2680 state.getIndexedUniformBuffer(blockBinding);
2681
2682 if (uniformBuffer.get() == nullptr)
2683 {
2684 // undefined behaviour
2685 return {GL_INVALID_OPERATION, kErrorUniformBufferUnbound};
2686 }
2687
2688 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2689 if (uniformBufferSize < uniformBlock.dataSize)
2690 {
2691 // undefined behaviour
2692 return {GL_INVALID_OPERATION, kErrorUniformBufferTooSmall};
2693 }
2694
2695 if (extensions.webglCompatibility &&
2696 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2697 {
2698 return {GL_INVALID_OPERATION, kErrorUniformBufferBoundForTransformFeedback};
2699 }
2700 }
2701
2702 // Do some additonal WebGL-specific validation
2703 if (extensions.webglCompatibility)
2704 {
2705 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2706 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2707 transformFeedbackObject->buffersBoundForOtherUse())
2708 {
2709 return {GL_INVALID_OPERATION, kErrorTransformFeedbackBufferDoubleBound};
2710 }
2711
2712 // Detect rendering feedback loops for WebGL.
2713 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2714 {
2715 return {GL_INVALID_OPERATION, kErrorFeedbackLoop};
2716 }
2717
2718 // Detect that the vertex shader input types match the attribute types
2719 if (!ValidateVertexShaderAttributeTypeMatch(context))
2720 {
2721 return {GL_INVALID_OPERATION, kErrorVertexShaderTypeMismatch};
2722 }
2723
2724 // Detect that the color buffer types match the fragment shader output types
2725 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2726 {
2727 return {GL_INVALID_OPERATION, kErrorDrawBufferTypeMismatch};
2728 }
2729 }
2730 }
2731
2732 return {GL_NO_ERROR, nullptr};
2733}
2734
Jamie Madill493f9572018-05-24 19:52:15 -04002735bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002736{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002737 const Extensions &extensions = context->getExtensions();
2738
Jamie Madill1aeb1312014-06-20 13:21:25 -04002739 switch (mode)
2740 {
Jamie Madill493f9572018-05-24 19:52:15 -04002741 case PrimitiveMode::Points:
2742 case PrimitiveMode::Lines:
2743 case PrimitiveMode::LineLoop:
2744 case PrimitiveMode::LineStrip:
2745 case PrimitiveMode::Triangles:
2746 case PrimitiveMode::TriangleStrip:
2747 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002748 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002749
Jamie Madill493f9572018-05-24 19:52:15 -04002750 case PrimitiveMode::LinesAdjacency:
2751 case PrimitiveMode::LineStripAdjacency:
2752 case PrimitiveMode::TrianglesAdjacency:
2753 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002754 if (!extensions.geometryShader)
2755 {
2756 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2757 return false;
2758 }
2759 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002760 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002761 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002762 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002763 }
2764
Jamie Madill250d33f2014-06-06 17:09:03 -04002765 if (count < 0)
2766 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002767 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002768 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002769 }
2770
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002771 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002772
Jamie Madille7d80f32018-08-08 15:49:23 -04002773 const ErrorAndMessage &errorAndMessage = ValidateDrawStates(context);
2774 if (errorAndMessage.errorType != GL_NO_ERROR)
Jamie Madill250d33f2014-06-06 17:09:03 -04002775 {
Jamie Madille7d80f32018-08-08 15:49:23 -04002776 if (errorAndMessage.message)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002777 {
Jamie Madille7d80f32018-08-08 15:49:23 -04002778 context->handleError(Error(errorAndMessage.errorType, errorAndMessage.message));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002779 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002780 else
Jamie Madill2da53562018-08-01 11:34:47 -04002781 {
Jamie Madille7d80f32018-08-08 15:49:23 -04002782 context->handleError(Error(errorAndMessage.errorType));
Jamie Madill2da53562018-08-01 11:34:47 -04002783 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002784 return false;
Jamie Madill2da53562018-08-01 11:34:47 -04002785 }
2786
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002787 // If we are running GLES1, there is no current program.
2788 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002789 {
Jamie Madill43da7c42018-08-01 11:34:49 -04002790 Program *program = state.getProgram();
Jamie Madille7d80f32018-08-08 15:49:23 -04002791 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002792
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002793 // Do geometry shader specific validations
2794 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002795 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002796 if (!IsCompatibleDrawModeWithGeometryShader(
2797 mode, program->getGeometryShaderInputPrimitiveType()))
2798 {
2799 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2800 IncompatibleDrawModeAgainstGeometryShader);
2801 return false;
2802 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002803 }
Geoff Lange0cff192017-05-30 13:04:56 -04002804
Jamie Madille7d80f32018-08-08 15:49:23 -04002805 if (extensions.webglCompatibility && count > 0)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002806 {
Jamie Madille7d80f32018-08-08 15:49:23 -04002807 const VertexArray *vao = context->getGLState().getVertexArray();
2808 if (vao->hasTransformFeedbackBindingConflict(context))
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002809 {
2810 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Jamie Madille7d80f32018-08-08 15:49:23 -04002811 VertexBufferBoundForTransformFeedback);
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002812 return false;
2813 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002814 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002815 }
2816
Jamie Madill9fdaa492018-02-16 10:52:11 -05002817 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002818}
2819
Jamie Madill5b772312018-03-08 20:28:32 -05002820bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002821 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002822 GLint first,
2823 GLsizei count,
2824 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002825{
Jamie Madillfd716582014-06-06 17:09:04 -04002826 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002827 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002828 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002829 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002830 }
2831
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002832 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04002833 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002834 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002835 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002836 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002837 if (!ValidateTransformFeedbackPrimitiveMode(context,
2838 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002839 {
James Darpinian30b604d2018-03-12 17:26:57 -07002840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2841 return false;
2842 }
2843
2844 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2845 {
2846 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2847 return false;
2848 }
Jamie Madillfd716582014-06-06 17:09:04 -04002849 }
2850
Jiajia Qind9671222016-11-29 16:30:31 +08002851 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002852 {
2853 return false;
2854 }
2855
Corentin Wallez71168a02016-12-19 15:11:18 -08002856 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002857 // - first < 0 has been checked as an error condition.
2858 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002859 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002860 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002861 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002862 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002863 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2864 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2865 {
2866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2867 return false;
2868 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002869
Jamie Madill2da53562018-08-01 11:34:47 -04002870 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002871 {
2872 return false;
2873 }
Jamie Madillfd716582014-06-06 17:09:04 -04002874 }
2875
2876 return true;
2877}
2878
He Yunchaoced53ae2016-11-29 15:00:51 +08002879bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002880 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002881 GLint first,
2882 GLsizei count,
2883 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002884{
Geoff Lang63c5a592017-09-27 14:08:16 -04002885 if (!context->getExtensions().instancedArrays)
2886 {
2887 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2888 return false;
2889 }
2890
Corentin Wallez170efbf2017-05-02 13:45:01 -04002891 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002892 {
2893 return false;
2894 }
2895
Corentin Wallez0dc97812017-06-22 14:38:44 -04002896 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002897}
2898
Jamie Madill493f9572018-05-24 19:52:15 -04002899bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002900{
Jamie Madill250d33f2014-06-06 17:09:03 -04002901 switch (type)
2902 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002903 case GL_UNSIGNED_BYTE:
2904 case GL_UNSIGNED_SHORT:
2905 break;
2906 case GL_UNSIGNED_INT:
2907 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2908 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002910 return false;
2911 }
2912 break;
2913 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002915 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002916 }
2917
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002918 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002919
Jamie Madill43da7c42018-08-01 11:34:49 -04002920 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002921 if (curTransformFeedback && curTransformFeedback->isActive() &&
2922 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002923 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002924 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2925 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2926 if (context->getExtensions().geometryShader)
2927 {
2928 if (!ValidateTransformFeedbackPrimitiveMode(
2929 context, curTransformFeedback->getPrimitiveMode(), mode))
2930 {
2931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2932 return false;
2933 }
2934 }
2935 else
2936 {
2937 // It is an invalid operation to call DrawElements, DrawRangeElements or
2938 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2939 // 86)
2940 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2941 UnsupportedDrawModeForTransformFeedback);
2942 return false;
2943 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002944 }
2945
Jiajia Qind9671222016-11-29 16:30:31 +08002946 return true;
2947}
2948
Jamie Madill5b772312018-03-08 20:28:32 -05002949bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002950 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002951 GLsizei count,
2952 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002953 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002954 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002955{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002956 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08002957 return false;
2958
2959 const State &state = context->getGLState();
2960
Corentin Wallez170efbf2017-05-02 13:45:01 -04002961 if (!ValidateDrawBase(context, mode, count))
2962 {
2963 return false;
2964 }
2965
Jamie Madill43da7c42018-08-01 11:34:49 -04002966 const VertexArray *vao = state.getVertexArray();
2967 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002968
Jamie Madill43da7c42018-08-01 11:34:49 -04002969 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002970
2971 if (context->getExtensions().webglCompatibility)
2972 {
2973 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2974 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2975 {
2976 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2977 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2978 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002979 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002980 return false;
2981 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002982
2983 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2984 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2985 // error is generated.
2986 if (reinterpret_cast<intptr_t>(indices) < 0)
2987 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002988 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002989 return false;
2990 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002991 }
Jamie Madillcc73f242018-08-01 11:34:48 -04002992 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
2993 {
2994 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
2995 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2996 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2997 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2998 return false;
2999 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003000
3001 if (context->getExtensions().webglCompatibility ||
3002 !context->getGLState().areClientArraysEnabled())
3003 {
Brandon Jones2a018152018-06-08 15:59:26 -07003004 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003005 {
3006 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003007 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3008 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003009 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003010 return false;
3011 }
3012 }
3013
Jamie Madill9fdaa492018-02-16 10:52:11 -05003014 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003015 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003016 // This is an application error that would normally result in a crash, but we catch it and
3017 // return an error
3018 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3019 return false;
3020 }
3021
3022 if (count > 0 && elementArrayBuffer)
3023 {
3024 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3025 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3026 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3027 constexpr uint64_t kMaxTypeSize = 8;
3028 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3029 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3030 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3031
3032 uint64_t typeSize = typeBytes;
3033 uint64_t elementCount = static_cast<uint64_t>(count);
3034 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3035
3036 // Doing the multiplication here is overflow-safe
3037 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3038
3039 // The offset can be any value, check for overflows
3040 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3041 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003042 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003043 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3044 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003045 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003046
3047 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3048 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003049 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3051 return false;
3052 }
3053
3054 ASSERT(isPow2(typeSize) && typeSize > 0);
3055 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3056 {
3057 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003058 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003059 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003060
3061 if (context->getExtensions().webglCompatibility &&
3062 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3063 {
3064 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3065 ElementArrayBufferBoundForTransformFeedback);
3066 return false;
3067 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003068 }
3069
Jamie Madill2da53562018-08-01 11:34:47 -04003070 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003071 {
3072 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003073 const DrawCallParams &params = context->getParams<DrawCallParams>();
3074 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3075 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003076
3077 // If we use an index greater than our maximum supported index range, return an error.
3078 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3079 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003080 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003081 {
3082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3083 return false;
3084 }
3085
Jamie Madill2da53562018-08-01 11:34:47 -04003086 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003087 {
3088 return false;
3089 }
3090
3091 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003092 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003093 }
3094
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003095 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003096}
3097
Jamie Madill5b772312018-03-08 20:28:32 -05003098bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003099 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003100 GLsizei count,
3101 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003102 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003103 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003104{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003105 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003106}
3107
Geoff Lang3edfe032015-09-04 16:38:24 -04003108bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003109 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003110 GLsizei count,
3111 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003112 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003113 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003114{
Geoff Lang63c5a592017-09-27 14:08:16 -04003115 if (!context->getExtensions().instancedArrays)
3116 {
3117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3118 return false;
3119 }
3120
Corentin Wallez170efbf2017-05-02 13:45:01 -04003121 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003122 {
3123 return false;
3124 }
3125
Corentin Wallez0dc97812017-06-22 14:38:44 -04003126 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003127}
3128
He Yunchaoced53ae2016-11-29 15:00:51 +08003129bool ValidateFramebufferTextureBase(Context *context,
3130 GLenum target,
3131 GLenum attachment,
3132 GLuint texture,
3133 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003134{
Geoff Lange8afa902017-09-27 15:00:43 -04003135 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003136 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003137 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003138 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003139 }
3140
3141 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003142 {
3143 return false;
3144 }
3145
Jamie Madill55ec3b12014-07-03 10:38:57 -04003146 if (texture != 0)
3147 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003148 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003149
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003150 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003152 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003153 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003154 }
3155
3156 if (level < 0)
3157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003158 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003159 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003160 }
3161 }
3162
Jamie Madill43da7c42018-08-01 11:34:49 -04003163 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003164 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003165
Jamie Madill84115c92015-04-23 15:00:07 -04003166 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003169 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003170 }
3171
3172 return true;
3173}
3174
Geoff Langb1196682014-07-23 13:47:29 -04003175bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003176{
3177 if (program == 0)
3178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003179 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003180 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003181 }
3182
Jamie Madill43da7c42018-08-01 11:34:49 -04003183 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003184 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003185 {
3186 return false;
3187 }
3188
Jamie Madill0063c512014-08-25 15:47:53 -04003189 if (!programObject || !programObject->isLinked())
3190 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003191 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003192 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003193 }
3194
Geoff Lang7dd2e102014-11-10 15:19:26 -05003195 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003197 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003198 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003199 }
3200
Jamie Madill0063c512014-08-25 15:47:53 -04003201 return true;
3202}
3203
Geoff Langf41d0ee2016-10-07 13:04:23 -04003204static bool ValidateSizedGetUniform(Context *context,
3205 GLuint program,
3206 GLint location,
3207 GLsizei bufSize,
3208 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003209{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003210 if (length)
3211 {
3212 *length = 0;
3213 }
3214
Jamie Madill78f41802014-08-25 15:47:55 -04003215 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003216 {
Jamie Madill78f41802014-08-25 15:47:55 -04003217 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003218 }
3219
Geoff Langf41d0ee2016-10-07 13:04:23 -04003220 if (bufSize < 0)
3221 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003222 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003223 return false;
3224 }
3225
Jamie Madill43da7c42018-08-01 11:34:49 -04003226 Program *programObject = context->getProgram(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003227 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003228
Jamie Madill78f41802014-08-25 15:47:55 -04003229 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003230 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003231 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003232 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003233 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003235 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003236 }
3237
Geoff Langf41d0ee2016-10-07 13:04:23 -04003238 if (length)
3239 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003240 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003241 }
3242
Jamie Madill0063c512014-08-25 15:47:53 -04003243 return true;
3244}
3245
He Yunchaoced53ae2016-11-29 15:00:51 +08003246bool ValidateGetnUniformfvEXT(Context *context,
3247 GLuint program,
3248 GLint location,
3249 GLsizei bufSize,
3250 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003251{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003252 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003253}
3254
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003255bool ValidateGetnUniformfvRobustANGLE(Context *context,
3256 GLuint program,
3257 GLint location,
3258 GLsizei bufSize,
3259 GLsizei *length,
3260 GLfloat *params)
3261{
3262 UNIMPLEMENTED();
3263 return false;
3264}
3265
He Yunchaoced53ae2016-11-29 15:00:51 +08003266bool ValidateGetnUniformivEXT(Context *context,
3267 GLuint program,
3268 GLint location,
3269 GLsizei bufSize,
3270 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003271{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003272 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3273}
3274
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003275bool ValidateGetnUniformivRobustANGLE(Context *context,
3276 GLuint program,
3277 GLint location,
3278 GLsizei bufSize,
3279 GLsizei *length,
3280 GLint *params)
3281{
3282 UNIMPLEMENTED();
3283 return false;
3284}
3285
3286bool ValidateGetnUniformuivRobustANGLE(Context *context,
3287 GLuint program,
3288 GLint location,
3289 GLsizei bufSize,
3290 GLsizei *length,
3291 GLuint *params)
3292{
3293 UNIMPLEMENTED();
3294 return false;
3295}
3296
Geoff Langf41d0ee2016-10-07 13:04:23 -04003297bool ValidateGetUniformfvRobustANGLE(Context *context,
3298 GLuint program,
3299 GLint location,
3300 GLsizei bufSize,
3301 GLsizei *length,
3302 GLfloat *params)
3303{
3304 if (!ValidateRobustEntryPoint(context, bufSize))
3305 {
3306 return false;
3307 }
3308
Brandon Jonesd1049182018-03-28 10:02:20 -07003309 GLsizei writeLength = 0;
3310
Geoff Langf41d0ee2016-10-07 13:04:23 -04003311 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003312 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3313 {
3314 return false;
3315 }
3316
3317 SetRobustLengthParam(length, writeLength);
3318
3319 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003320}
3321
3322bool ValidateGetUniformivRobustANGLE(Context *context,
3323 GLuint program,
3324 GLint location,
3325 GLsizei bufSize,
3326 GLsizei *length,
3327 GLint *params)
3328{
3329 if (!ValidateRobustEntryPoint(context, bufSize))
3330 {
3331 return false;
3332 }
3333
Brandon Jonesd1049182018-03-28 10:02:20 -07003334 GLsizei writeLength = 0;
3335
Geoff Langf41d0ee2016-10-07 13:04:23 -04003336 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003337 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3338 {
3339 return false;
3340 }
3341
3342 SetRobustLengthParam(length, writeLength);
3343
3344 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003345}
3346
3347bool ValidateGetUniformuivRobustANGLE(Context *context,
3348 GLuint program,
3349 GLint location,
3350 GLsizei bufSize,
3351 GLsizei *length,
3352 GLuint *params)
3353{
3354 if (!ValidateRobustEntryPoint(context, bufSize))
3355 {
3356 return false;
3357 }
3358
3359 if (context->getClientMajorVersion() < 3)
3360 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003361 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003362 return false;
3363 }
3364
Brandon Jonesd1049182018-03-28 10:02:20 -07003365 GLsizei writeLength = 0;
3366
Geoff Langf41d0ee2016-10-07 13:04:23 -04003367 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003368 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3369 {
3370 return false;
3371 }
3372
3373 SetRobustLengthParam(length, writeLength);
3374
3375 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003376}
3377
He Yunchaoced53ae2016-11-29 15:00:51 +08003378bool ValidateDiscardFramebufferBase(Context *context,
3379 GLenum target,
3380 GLsizei numAttachments,
3381 const GLenum *attachments,
3382 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003383{
3384 if (numAttachments < 0)
3385 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003386 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003387 return false;
3388 }
3389
3390 for (GLsizei i = 0; i < numAttachments; ++i)
3391 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003392 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003393 {
3394 if (defaultFramebuffer)
3395 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003397 return false;
3398 }
3399
3400 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003402 context->handleError(InvalidOperation() << "Requested color attachment is "
3403 "greater than the maximum supported "
3404 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003405 return false;
3406 }
3407 }
3408 else
3409 {
3410 switch (attachments[i])
3411 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003412 case GL_DEPTH_ATTACHMENT:
3413 case GL_STENCIL_ATTACHMENT:
3414 case GL_DEPTH_STENCIL_ATTACHMENT:
3415 if (defaultFramebuffer)
3416 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003417 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3418 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003419 return false;
3420 }
3421 break;
3422 case GL_COLOR:
3423 case GL_DEPTH:
3424 case GL_STENCIL:
3425 if (!defaultFramebuffer)
3426 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003427 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3428 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003429 return false;
3430 }
3431 break;
3432 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003433 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003434 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003435 }
3436 }
3437 }
3438
3439 return true;
3440}
3441
Austin Kinross6ee1e782015-05-29 17:05:37 -07003442bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3443{
Jamie Madill007530e2017-12-28 14:27:04 -05003444 if (!context->getExtensions().debugMarker)
3445 {
3446 // The debug marker calls should not set error state
3447 // However, it seems reasonable to set an error state if the extension is not enabled
3448 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3449 return false;
3450 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003451
Jamie Madill007530e2017-12-28 14:27:04 -05003452 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003453 if (length < 0)
3454 {
3455 return false;
3456 }
3457
3458 if (marker == nullptr)
3459 {
3460 return false;
3461 }
3462
3463 return true;
3464}
3465
3466bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3467{
Jamie Madill007530e2017-12-28 14:27:04 -05003468 if (!context->getExtensions().debugMarker)
3469 {
3470 // The debug marker calls should not set error state
3471 // However, it seems reasonable to set an error state if the extension is not enabled
3472 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3473 return false;
3474 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003475
Jamie Madill007530e2017-12-28 14:27:04 -05003476 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003477 if (length < 0)
3478 {
3479 return false;
3480 }
3481
3482 if (length > 0 && marker == nullptr)
3483 {
3484 return false;
3485 }
3486
3487 return true;
3488}
3489
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003490bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003491{
Geoff Langa8406172015-07-21 16:53:39 -04003492 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003494 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003495 return false;
3496 }
3497
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003498 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003499 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003500 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003501 if (!context->getExtensions().eglImage)
3502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003503 context->handleError(InvalidEnum()
3504 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003505 }
3506 break;
3507
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003508 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003509 if (!context->getExtensions().eglImageExternal)
3510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003511 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3512 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003513 }
Geoff Langa8406172015-07-21 16:53:39 -04003514 break;
3515
3516 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003517 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003518 return false;
3519 }
3520
Rafael Cintron05a449a2018-06-20 18:08:04 -07003521 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003522
Jamie Madill61e16b42017-06-19 11:13:23 -04003523 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003524 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003526 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003527 return false;
3528 }
3529
Jamie Madill007530e2017-12-28 14:27:04 -05003530 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003532 context->handleError(InvalidOperation()
3533 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003534 return false;
3535 }
3536
Geoff Langca271392017-04-05 12:30:00 -04003537 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003538 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003539 if (!textureCaps.texturable)
3540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003541 context->handleError(InvalidOperation()
3542 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003543 return false;
3544 }
3545
Geoff Langdcab33b2015-07-21 13:03:16 -04003546 return true;
3547}
3548
3549bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003550 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003551 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003552{
Geoff Langa8406172015-07-21 16:53:39 -04003553 if (!context->getExtensions().eglImage)
3554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003555 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003556 return false;
3557 }
3558
3559 switch (target)
3560 {
3561 case GL_RENDERBUFFER:
3562 break;
3563
3564 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003565 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003566 return false;
3567 }
3568
Rafael Cintron05a449a2018-06-20 18:08:04 -07003569 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003570
Jamie Madill61e16b42017-06-19 11:13:23 -04003571 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003572 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003574 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003575 return false;
3576 }
3577
Geoff Langca271392017-04-05 12:30:00 -04003578 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003579 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003580 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003582 context->handleError(InvalidOperation()
3583 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003584 return false;
3585 }
3586
Geoff Langdcab33b2015-07-21 13:03:16 -04003587 return true;
3588}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003589
3590bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3591{
Geoff Lang36167ab2015-12-07 10:27:14 -05003592 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003593 {
3594 // The default VAO should always exist
3595 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003596 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003597 return false;
3598 }
3599
3600 return true;
3601}
3602
Geoff Langc5629752015-12-07 16:29:04 -05003603bool ValidateProgramBinaryBase(Context *context,
3604 GLuint program,
3605 GLenum binaryFormat,
3606 const void *binary,
3607 GLint length)
3608{
3609 Program *programObject = GetValidProgram(context, program);
3610 if (programObject == nullptr)
3611 {
3612 return false;
3613 }
3614
3615 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3616 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3617 programBinaryFormats.end())
3618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003619 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003620 return false;
3621 }
3622
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003623 if (context->hasActiveTransformFeedback(program))
3624 {
3625 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003626 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3627 "is associated with an active transform "
3628 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003629 return false;
3630 }
3631
Geoff Langc5629752015-12-07 16:29:04 -05003632 return true;
3633}
3634
3635bool ValidateGetProgramBinaryBase(Context *context,
3636 GLuint program,
3637 GLsizei bufSize,
3638 GLsizei *length,
3639 GLenum *binaryFormat,
3640 void *binary)
3641{
3642 Program *programObject = GetValidProgram(context, program);
3643 if (programObject == nullptr)
3644 {
3645 return false;
3646 }
3647
3648 if (!programObject->isLinked())
3649 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003650 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003651 return false;
3652 }
3653
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003654 if (context->getCaps().programBinaryFormats.empty())
3655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003656 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003657 return false;
3658 }
3659
Geoff Langc5629752015-12-07 16:29:04 -05003660 return true;
3661}
Jamie Madillc29968b2016-01-20 11:17:23 -05003662
Jamie Madill5b772312018-03-08 20:28:32 -05003663bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003664{
3665 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003666 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003668 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3669 return false;
3670 }
3671 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3672 {
3673 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003674 return false;
3675 }
3676
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003677 ASSERT(context->getGLState().getDrawFramebuffer());
3678 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003679 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3680
3681 // This should come first before the check for the default frame buffer
3682 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3683 // rather than INVALID_OPERATION
3684 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3685 {
3686 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3687
3688 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003689 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3690 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003691 {
3692 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003693 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3694 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3695 // 3.1 is still a bit ambiguous about the error, but future specs are
3696 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003697 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003698 return false;
3699 }
3700 else if (bufs[colorAttachment] >= maxColorAttachment)
3701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003702 context->handleError(InvalidOperation()
3703 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003704 return false;
3705 }
3706 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3707 frameBufferId != 0)
3708 {
3709 // INVALID_OPERATION-GL is bound to buffer and ith argument
3710 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003711 context->handleError(InvalidOperation()
3712 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003713 return false;
3714 }
3715 }
3716
3717 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3718 // and n is not 1 or bufs is bound to value other than BACK and NONE
3719 if (frameBufferId == 0)
3720 {
3721 if (n != 1)
3722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003723 context->handleError(InvalidOperation()
3724 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003725 return false;
3726 }
3727
3728 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003730 context->handleError(
3731 InvalidOperation()
3732 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003733 return false;
3734 }
3735 }
3736
3737 return true;
3738}
3739
Geoff Lang496c02d2016-10-20 11:38:11 -07003740bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003741 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003742 GLenum pname,
3743 GLsizei *length,
3744 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003745{
Geoff Lang496c02d2016-10-20 11:38:11 -07003746 if (length)
3747 {
3748 *length = 0;
3749 }
3750
3751 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3752 {
3753 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 InvalidOperation()
3755 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003756 return false;
3757 }
3758
Corentin Walleze4477002017-12-01 14:39:58 -05003759 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003760 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003761 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003762 return false;
3763 }
3764
Geoff Lang496c02d2016-10-20 11:38:11 -07003765 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003766 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003767 case GL_BUFFER_MAP_POINTER:
3768 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003769
Geoff Lang496c02d2016-10-20 11:38:11 -07003770 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003772 return false;
3773 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003774
3775 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3776 // target bound to zero generate an INVALID_OPERATION error."
3777 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003778 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003780 context->handleError(InvalidOperation()
3781 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003782 return false;
3783 }
3784
Geoff Lang496c02d2016-10-20 11:38:11 -07003785 if (length)
3786 {
3787 *length = 1;
3788 }
3789
Olli Etuaho4f667482016-03-30 15:56:35 +03003790 return true;
3791}
3792
Corentin Wallez336129f2017-10-17 15:55:40 -04003793bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003794{
Corentin Walleze4477002017-12-01 14:39:58 -05003795 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003796 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003797 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003798 return false;
3799 }
3800
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003801 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003802
3803 if (buffer == nullptr || !buffer->isMapped())
3804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003805 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003806 return false;
3807 }
3808
3809 return true;
3810}
3811
3812bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003813 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003814 GLintptr offset,
3815 GLsizeiptr length,
3816 GLbitfield access)
3817{
Corentin Walleze4477002017-12-01 14:39:58 -05003818 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003819 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003820 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003821 return false;
3822 }
3823
Brandon Jones6cad5662017-06-14 13:25:13 -07003824 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003825 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003826 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3827 return false;
3828 }
3829
3830 if (length < 0)
3831 {
3832 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003833 return false;
3834 }
3835
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003836 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003837
3838 if (!buffer)
3839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003840 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003841 return false;
3842 }
3843
3844 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003845 CheckedNumeric<size_t> checkedOffset(offset);
3846 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003847
Jamie Madille2e406c2016-06-02 13:04:10 -04003848 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003849 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003850 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003851 return false;
3852 }
3853
3854 // Check for invalid bits in the mask
3855 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3856 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3857 GL_MAP_UNSYNCHRONIZED_BIT;
3858
3859 if (access & ~(allAccessBits))
3860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003861 context->handleError(InvalidValue()
3862 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 return false;
3864 }
3865
3866 if (length == 0)
3867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003868 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003869 return false;
3870 }
3871
3872 if (buffer->isMapped())
3873 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003874 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003875 return false;
3876 }
3877
3878 // Check for invalid bit combinations
3879 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003881 context->handleError(InvalidOperation()
3882 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003883 return false;
3884 }
3885
3886 GLbitfield writeOnlyBits =
3887 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3888
3889 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003891 context->handleError(InvalidOperation()
3892 << "Invalid access bits when mapping buffer for reading: 0x"
3893 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003894 return false;
3895 }
3896
3897 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003899 context->handleError(
3900 InvalidOperation()
3901 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003902 return false;
3903 }
Geoff Lang79f71042017-08-14 16:43:43 -04003904
3905 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003906}
3907
3908bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003909 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003910 GLintptr offset,
3911 GLsizeiptr length)
3912{
Brandon Jones6cad5662017-06-14 13:25:13 -07003913 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003915 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3916 return false;
3917 }
3918
3919 if (length < 0)
3920 {
3921 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003922 return false;
3923 }
3924
Corentin Walleze4477002017-12-01 14:39:58 -05003925 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003926 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003927 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003928 return false;
3929 }
3930
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003931 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003932
3933 if (buffer == nullptr)
3934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003935 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003936 return false;
3937 }
3938
3939 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003941 context->handleError(InvalidOperation()
3942 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003943 return false;
3944 }
3945
3946 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003947 CheckedNumeric<size_t> checkedOffset(offset);
3948 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003949
Jamie Madille2e406c2016-06-02 13:04:10 -04003950 if (!checkedSize.IsValid() ||
3951 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003953 context->handleError(InvalidValue()
3954 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003955 return false;
3956 }
3957
3958 return true;
3959}
3960
Olli Etuaho41997e72016-03-10 13:38:39 +02003961bool ValidateGenOrDelete(Context *context, GLint n)
3962{
3963 if (n < 0)
3964 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003965 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003966 return false;
3967 }
3968 return true;
3969}
3970
Jamie Madill5b772312018-03-08 20:28:32 -05003971bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003972{
3973 if (!context->getExtensions().robustClientMemory)
3974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003975 context->handleError(InvalidOperation()
3976 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003977 return false;
3978 }
3979
3980 if (bufSize < 0)
3981 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003982 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003983 return false;
3984 }
3985
3986 return true;
3987}
3988
Jamie Madill5b772312018-03-08 20:28:32 -05003989bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003990{
3991 if (bufSize < numParams)
3992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003993 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3994 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003995 return false;
3996 }
3997
3998 return true;
3999}
4000
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004001bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004002 GLenum target,
4003 GLenum attachment,
4004 GLenum pname,
4005 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004006{
Geoff Lange8afa902017-09-27 15:00:43 -04004007 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004009 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004010 return false;
4011 }
4012
4013 int clientVersion = context->getClientMajorVersion();
4014
4015 switch (pname)
4016 {
4017 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4018 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4019 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4020 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4021 break;
4022
Martin Radeve5285d22017-07-14 16:23:53 +03004023 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4024 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4025 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4026 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4027 if (clientVersion < 3 || !context->getExtensions().multiview)
4028 {
4029 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4030 return false;
4031 }
4032 break;
4033
Geoff Langff5b2d52016-09-07 11:32:23 -04004034 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4035 if (clientVersion < 3 && !context->getExtensions().sRGB)
4036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004037 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004038 return false;
4039 }
4040 break;
4041
4042 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4043 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4044 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4045 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4046 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4047 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4048 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4049 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4050 if (clientVersion < 3)
4051 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004052 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004053 return false;
4054 }
4055 break;
4056
Jiawei Shaoa8802472018-05-28 11:17:47 +08004057 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4058 if (!context->getExtensions().geometryShader)
4059 {
4060 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4061 return false;
4062 }
4063 break;
4064
Geoff Langff5b2d52016-09-07 11:32:23 -04004065 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004066 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004067 return false;
4068 }
4069
4070 // Determine if the attachment is a valid enum
4071 switch (attachment)
4072 {
4073 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004074 case GL_DEPTH:
4075 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004076 if (clientVersion < 3)
4077 {
Geoff Langfa125c92017-10-24 13:01:46 -04004078 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004079 return false;
4080 }
4081 break;
4082
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004083 case GL_DEPTH_STENCIL_ATTACHMENT:
4084 if (clientVersion < 3 && !context->isWebGL1())
4085 {
4086 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4087 return false;
4088 }
4089 break;
4090
Geoff Langfa125c92017-10-24 13:01:46 -04004091 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004092 case GL_DEPTH_ATTACHMENT:
4093 case GL_STENCIL_ATTACHMENT:
4094 break;
4095
4096 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004097 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4098 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004099 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4100 {
Geoff Langfa125c92017-10-24 13:01:46 -04004101 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004102 return false;
4103 }
4104 break;
4105 }
4106
4107 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4108 ASSERT(framebuffer);
4109
4110 if (framebuffer->id() == 0)
4111 {
4112 if (clientVersion < 3)
4113 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004115 return false;
4116 }
4117
4118 switch (attachment)
4119 {
4120 case GL_BACK:
4121 case GL_DEPTH:
4122 case GL_STENCIL:
4123 break;
4124
4125 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004127 return false;
4128 }
4129 }
4130 else
4131 {
4132 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4133 {
4134 // Valid attachment query
4135 }
4136 else
4137 {
4138 switch (attachment)
4139 {
4140 case GL_DEPTH_ATTACHMENT:
4141 case GL_STENCIL_ATTACHMENT:
4142 break;
4143
4144 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004145 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004147 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004148 return false;
4149 }
4150 break;
4151
4152 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004154 return false;
4155 }
4156 }
4157 }
4158
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004159 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004160 if (attachmentObject)
4161 {
4162 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4163 attachmentObject->type() == GL_TEXTURE ||
4164 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4165
4166 switch (pname)
4167 {
4168 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4169 if (attachmentObject->type() != GL_RENDERBUFFER &&
4170 attachmentObject->type() != GL_TEXTURE)
4171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004172 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004173 return false;
4174 }
4175 break;
4176
4177 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4178 if (attachmentObject->type() != GL_TEXTURE)
4179 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004181 return false;
4182 }
4183 break;
4184
4185 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4186 if (attachmentObject->type() != GL_TEXTURE)
4187 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004188 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004189 return false;
4190 }
4191 break;
4192
4193 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4194 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4195 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004196 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004197 return false;
4198 }
4199 break;
4200
4201 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4202 if (attachmentObject->type() != GL_TEXTURE)
4203 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004204 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004205 return false;
4206 }
4207 break;
4208
4209 default:
4210 break;
4211 }
4212 }
4213 else
4214 {
4215 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4216 // is NONE, then querying any other pname will generate INVALID_ENUM.
4217
4218 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4219 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4220 // INVALID_OPERATION for all other pnames
4221
4222 switch (pname)
4223 {
4224 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4225 break;
4226
4227 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4228 if (clientVersion < 3)
4229 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004230 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004231 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004232 return false;
4233 }
4234 break;
4235
4236 default:
4237 if (clientVersion < 3)
4238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004239 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004240 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004241 return false;
4242 }
4243 else
4244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004245 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004246 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004247 return false;
4248 }
4249 }
4250 }
4251
Martin Radeve5285d22017-07-14 16:23:53 +03004252 if (numParams)
4253 {
4254 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4255 {
4256 // Only when the viewport offsets are queried we can have a varying number of output
4257 // parameters.
4258 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4259 *numParams = numViews * 2;
4260 }
4261 else
4262 {
4263 // For all other queries we can have only one output parameter.
4264 *numParams = 1;
4265 }
4266 }
4267
Geoff Langff5b2d52016-09-07 11:32:23 -04004268 return true;
4269}
4270
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004271bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004272 GLenum target,
4273 GLenum attachment,
4274 GLenum pname,
4275 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004276 GLsizei *length,
4277 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004278{
4279 if (!ValidateRobustEntryPoint(context, bufSize))
4280 {
4281 return false;
4282 }
4283
Brandon Jonesd1049182018-03-28 10:02:20 -07004284 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004285 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004286 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004287 {
4288 return false;
4289 }
4290
Brandon Jonesd1049182018-03-28 10:02:20 -07004291 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004292 {
4293 return false;
4294 }
4295
Brandon Jonesd1049182018-03-28 10:02:20 -07004296 SetRobustLengthParam(length, numParams);
4297
Geoff Langff5b2d52016-09-07 11:32:23 -04004298 return true;
4299}
4300
Jamie Madill5b772312018-03-08 20:28:32 -05004301bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004302 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004303 GLenum pname,
4304 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004305 GLsizei *length,
4306 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004307{
4308 if (!ValidateRobustEntryPoint(context, bufSize))
4309 {
4310 return false;
4311 }
4312
Brandon Jonesd1049182018-03-28 10:02:20 -07004313 GLsizei numParams = 0;
4314
4315 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004316 {
4317 return false;
4318 }
4319
Brandon Jonesd1049182018-03-28 10:02:20 -07004320 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004321 {
4322 return false;
4323 }
4324
Brandon Jonesd1049182018-03-28 10:02:20 -07004325 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004326 return true;
4327}
4328
Jamie Madill5b772312018-03-08 20:28:32 -05004329bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004330 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004331 GLenum pname,
4332 GLsizei bufSize,
4333 GLsizei *length,
4334 GLint64 *params)
4335{
Brandon Jonesd1049182018-03-28 10:02:20 -07004336 GLsizei numParams = 0;
4337
Geoff Langebebe1c2016-10-14 12:01:31 -04004338 if (!ValidateRobustEntryPoint(context, bufSize))
4339 {
4340 return false;
4341 }
4342
Brandon Jonesd1049182018-03-28 10:02:20 -07004343 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004344 {
4345 return false;
4346 }
4347
Brandon Jonesd1049182018-03-28 10:02:20 -07004348 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004349 {
4350 return false;
4351 }
4352
Brandon Jonesd1049182018-03-28 10:02:20 -07004353 SetRobustLengthParam(length, numParams);
4354
Geoff Langff5b2d52016-09-07 11:32:23 -04004355 return true;
4356}
4357
Jamie Madill5b772312018-03-08 20:28:32 -05004358bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004359{
4360 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004361 if (numParams)
4362 {
4363 *numParams = 1;
4364 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004365
4366 Program *programObject = GetValidProgram(context, program);
4367 if (!programObject)
4368 {
4369 return false;
4370 }
4371
4372 switch (pname)
4373 {
4374 case GL_DELETE_STATUS:
4375 case GL_LINK_STATUS:
4376 case GL_VALIDATE_STATUS:
4377 case GL_INFO_LOG_LENGTH:
4378 case GL_ATTACHED_SHADERS:
4379 case GL_ACTIVE_ATTRIBUTES:
4380 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4381 case GL_ACTIVE_UNIFORMS:
4382 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4383 break;
4384
4385 case GL_PROGRAM_BINARY_LENGTH:
4386 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004388 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4389 "requires GL_OES_get_program_binary or "
4390 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004391 return false;
4392 }
4393 break;
4394
4395 case GL_ACTIVE_UNIFORM_BLOCKS:
4396 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4397 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4398 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4399 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4400 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4401 if (context->getClientMajorVersion() < 3)
4402 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004403 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004404 return false;
4405 }
4406 break;
4407
Yunchao He61afff12017-03-14 15:34:03 +08004408 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004409 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004410 if (context->getClientVersion() < Version(3, 1))
4411 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004412 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004413 return false;
4414 }
4415 break;
4416
Jiawei Shao6ae51612018-02-23 14:03:25 +08004417 case GL_COMPUTE_WORK_GROUP_SIZE:
4418 if (context->getClientVersion() < Version(3, 1))
4419 {
4420 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4421 return false;
4422 }
4423
4424 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4425 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4426 // program which has not been linked successfully, or which does not contain objects to
4427 // form a compute shader.
4428 if (!programObject->isLinked())
4429 {
4430 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4431 return false;
4432 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004433 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004434 {
4435 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4436 return false;
4437 }
4438 break;
4439
Jiawei Shao447bfac2018-03-14 14:23:40 +08004440 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4441 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4442 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4443 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4444 if (!context->getExtensions().geometryShader)
4445 {
4446 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4447 return false;
4448 }
4449
4450 // [EXT_geometry_shader] Chapter 7.12
4451 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4452 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4453 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4454 // successfully, or which does not contain objects to form a geometry shader.
4455 if (!programObject->isLinked())
4456 {
4457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4458 return false;
4459 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004460 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004461 {
4462 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4463 return false;
4464 }
4465 break;
4466
Geoff Langff5b2d52016-09-07 11:32:23 -04004467 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004468 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004469 return false;
4470 }
4471
4472 return true;
4473}
4474
4475bool ValidateGetProgramivRobustANGLE(Context *context,
4476 GLuint program,
4477 GLenum pname,
4478 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004479 GLsizei *length,
4480 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004481{
4482 if (!ValidateRobustEntryPoint(context, bufSize))
4483 {
4484 return false;
4485 }
4486
Brandon Jonesd1049182018-03-28 10:02:20 -07004487 GLsizei numParams = 0;
4488
4489 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004490 {
4491 return false;
4492 }
4493
Brandon Jonesd1049182018-03-28 10:02:20 -07004494 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004495 {
4496 return false;
4497 }
4498
Brandon Jonesd1049182018-03-28 10:02:20 -07004499 SetRobustLengthParam(length, numParams);
4500
Geoff Langff5b2d52016-09-07 11:32:23 -04004501 return true;
4502}
4503
Geoff Lang740d9022016-10-07 11:20:52 -04004504bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4505 GLenum target,
4506 GLenum pname,
4507 GLsizei bufSize,
4508 GLsizei *length,
4509 GLint *params)
4510{
4511 if (!ValidateRobustEntryPoint(context, bufSize))
4512 {
4513 return false;
4514 }
4515
Brandon Jonesd1049182018-03-28 10:02:20 -07004516 GLsizei numParams = 0;
4517
4518 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004519 {
4520 return false;
4521 }
4522
Brandon Jonesd1049182018-03-28 10:02:20 -07004523 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004524 {
4525 return false;
4526 }
4527
Brandon Jonesd1049182018-03-28 10:02:20 -07004528 SetRobustLengthParam(length, numParams);
4529
Geoff Lang740d9022016-10-07 11:20:52 -04004530 return true;
4531}
4532
Geoff Langd7d0ed32016-10-07 11:33:51 -04004533bool ValidateGetShaderivRobustANGLE(Context *context,
4534 GLuint shader,
4535 GLenum pname,
4536 GLsizei bufSize,
4537 GLsizei *length,
4538 GLint *params)
4539{
4540 if (!ValidateRobustEntryPoint(context, bufSize))
4541 {
4542 return false;
4543 }
4544
Brandon Jonesd1049182018-03-28 10:02:20 -07004545 GLsizei numParams = 0;
4546
4547 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004548 {
4549 return false;
4550 }
4551
Brandon Jonesd1049182018-03-28 10:02:20 -07004552 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004553 {
4554 return false;
4555 }
4556
Brandon Jonesd1049182018-03-28 10:02:20 -07004557 SetRobustLengthParam(length, numParams);
4558
Geoff Langd7d0ed32016-10-07 11:33:51 -04004559 return true;
4560}
4561
Geoff Langc1984ed2016-10-07 12:41:00 -04004562bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004563 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004564 GLenum pname,
4565 GLsizei bufSize,
4566 GLsizei *length,
4567 GLfloat *params)
4568{
4569 if (!ValidateRobustEntryPoint(context, bufSize))
4570 {
4571 return false;
4572 }
4573
Brandon Jonesd1049182018-03-28 10:02:20 -07004574 GLsizei numParams = 0;
4575
4576 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004577 {
4578 return false;
4579 }
4580
Brandon Jonesd1049182018-03-28 10:02:20 -07004581 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004582 {
4583 return false;
4584 }
4585
Brandon Jonesd1049182018-03-28 10:02:20 -07004586 SetRobustLengthParam(length, numParams);
4587
Geoff Langc1984ed2016-10-07 12:41:00 -04004588 return true;
4589}
4590
Geoff Langc1984ed2016-10-07 12:41:00 -04004591bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004592 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004593 GLenum pname,
4594 GLsizei bufSize,
4595 GLsizei *length,
4596 GLint *params)
4597{
Brandon Jonesd1049182018-03-28 10:02:20 -07004598
Geoff Langc1984ed2016-10-07 12:41:00 -04004599 if (!ValidateRobustEntryPoint(context, bufSize))
4600 {
4601 return false;
4602 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004603 GLsizei numParams = 0;
4604 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004605 {
4606 return false;
4607 }
4608
Brandon Jonesd1049182018-03-28 10:02:20 -07004609 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004610 {
4611 return false;
4612 }
4613
Brandon Jonesd1049182018-03-28 10:02:20 -07004614 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004615 return true;
4616}
4617
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004618bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4619 TextureType target,
4620 GLenum pname,
4621 GLsizei bufSize,
4622 GLsizei *length,
4623 GLint *params)
4624{
4625 UNIMPLEMENTED();
4626 return false;
4627}
4628
4629bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4630 TextureType target,
4631 GLenum pname,
4632 GLsizei bufSize,
4633 GLsizei *length,
4634 GLuint *params)
4635{
4636 UNIMPLEMENTED();
4637 return false;
4638}
4639
Geoff Langc1984ed2016-10-07 12:41:00 -04004640bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004641 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004642 GLenum pname,
4643 GLsizei bufSize,
4644 const GLfloat *params)
4645{
4646 if (!ValidateRobustEntryPoint(context, bufSize))
4647 {
4648 return false;
4649 }
4650
4651 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4652}
4653
Geoff Langc1984ed2016-10-07 12:41:00 -04004654bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004655 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004656 GLenum pname,
4657 GLsizei bufSize,
4658 const GLint *params)
4659{
4660 if (!ValidateRobustEntryPoint(context, bufSize))
4661 {
4662 return false;
4663 }
4664
4665 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4666}
4667
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004668bool ValidateTexParameterIivRobustANGLE(Context *context,
4669 TextureType target,
4670 GLenum pname,
4671 GLsizei bufSize,
4672 const GLint *params)
4673{
4674 UNIMPLEMENTED();
4675 return false;
4676}
4677
4678bool ValidateTexParameterIuivRobustANGLE(Context *context,
4679 TextureType target,
4680 GLenum pname,
4681 GLsizei bufSize,
4682 const GLuint *params)
4683{
4684 UNIMPLEMENTED();
4685 return false;
4686}
4687
Geoff Langc1984ed2016-10-07 12:41:00 -04004688bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4689 GLuint sampler,
4690 GLenum pname,
4691 GLuint bufSize,
4692 GLsizei *length,
4693 GLfloat *params)
4694{
4695 if (!ValidateRobustEntryPoint(context, bufSize))
4696 {
4697 return false;
4698 }
4699
Brandon Jonesd1049182018-03-28 10:02:20 -07004700 GLsizei numParams = 0;
4701
4702 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004703 {
4704 return false;
4705 }
4706
Brandon Jonesd1049182018-03-28 10:02:20 -07004707 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004708 {
4709 return false;
4710 }
4711
Brandon Jonesd1049182018-03-28 10:02:20 -07004712 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004713 return true;
4714}
4715
Geoff Langc1984ed2016-10-07 12:41:00 -04004716bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4717 GLuint sampler,
4718 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004719 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004720 GLsizei *length,
4721 GLint *params)
4722{
4723 if (!ValidateRobustEntryPoint(context, bufSize))
4724 {
4725 return false;
4726 }
4727
Brandon Jonesd1049182018-03-28 10:02:20 -07004728 GLsizei numParams = 0;
4729
4730 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004731 {
4732 return false;
4733 }
4734
Brandon Jonesd1049182018-03-28 10:02:20 -07004735 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004736 {
4737 return false;
4738 }
4739
Brandon Jonesd1049182018-03-28 10:02:20 -07004740 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004741 return true;
4742}
4743
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004744bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4745 GLuint sampler,
4746 GLenum pname,
4747 GLsizei bufSize,
4748 GLsizei *length,
4749 GLint *params)
4750{
4751 UNIMPLEMENTED();
4752 return false;
4753}
4754
4755bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4756 GLuint sampler,
4757 GLenum pname,
4758 GLsizei bufSize,
4759 GLsizei *length,
4760 GLuint *params)
4761{
4762 UNIMPLEMENTED();
4763 return false;
4764}
4765
Geoff Langc1984ed2016-10-07 12:41:00 -04004766bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4767 GLuint sampler,
4768 GLenum pname,
4769 GLsizei bufSize,
4770 const GLfloat *params)
4771{
4772 if (!ValidateRobustEntryPoint(context, bufSize))
4773 {
4774 return false;
4775 }
4776
4777 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4778}
4779
Geoff Langc1984ed2016-10-07 12:41:00 -04004780bool ValidateSamplerParameterivRobustANGLE(Context *context,
4781 GLuint sampler,
4782 GLenum pname,
4783 GLsizei bufSize,
4784 const GLint *params)
4785{
4786 if (!ValidateRobustEntryPoint(context, bufSize))
4787 {
4788 return false;
4789 }
4790
4791 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4792}
4793
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004794bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4795 GLuint sampler,
4796 GLenum pname,
4797 GLsizei bufSize,
4798 const GLint *param)
4799{
4800 UNIMPLEMENTED();
4801 return false;
4802}
4803
4804bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4805 GLuint sampler,
4806 GLenum pname,
4807 GLsizei bufSize,
4808 const GLuint *param)
4809{
4810 UNIMPLEMENTED();
4811 return false;
4812}
4813
Geoff Lang0b031062016-10-13 14:30:04 -04004814bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4815 GLuint index,
4816 GLenum pname,
4817 GLsizei bufSize,
4818 GLsizei *length,
4819 GLfloat *params)
4820{
4821 if (!ValidateRobustEntryPoint(context, bufSize))
4822 {
4823 return false;
4824 }
4825
Brandon Jonesd1049182018-03-28 10:02:20 -07004826 GLsizei writeLength = 0;
4827
4828 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004829 {
4830 return false;
4831 }
4832
Brandon Jonesd1049182018-03-28 10:02:20 -07004833 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004834 {
4835 return false;
4836 }
4837
Brandon Jonesd1049182018-03-28 10:02:20 -07004838 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004839 return true;
4840}
4841
Geoff Lang0b031062016-10-13 14:30:04 -04004842bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4843 GLuint index,
4844 GLenum pname,
4845 GLsizei bufSize,
4846 GLsizei *length,
4847 GLint *params)
4848{
4849 if (!ValidateRobustEntryPoint(context, bufSize))
4850 {
4851 return false;
4852 }
4853
Brandon Jonesd1049182018-03-28 10:02:20 -07004854 GLsizei writeLength = 0;
4855
4856 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004857 {
4858 return false;
4859 }
4860
Brandon Jonesd1049182018-03-28 10:02:20 -07004861 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004862 {
4863 return false;
4864 }
4865
Brandon Jonesd1049182018-03-28 10:02:20 -07004866 SetRobustLengthParam(length, writeLength);
4867
Geoff Lang0b031062016-10-13 14:30:04 -04004868 return true;
4869}
4870
Geoff Lang0b031062016-10-13 14:30:04 -04004871bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4872 GLuint index,
4873 GLenum pname,
4874 GLsizei bufSize,
4875 GLsizei *length,
4876 void **pointer)
4877{
4878 if (!ValidateRobustEntryPoint(context, bufSize))
4879 {
4880 return false;
4881 }
4882
Brandon Jonesd1049182018-03-28 10:02:20 -07004883 GLsizei writeLength = 0;
4884
4885 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004886 {
4887 return false;
4888 }
4889
Brandon Jonesd1049182018-03-28 10:02:20 -07004890 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004891 {
4892 return false;
4893 }
4894
Brandon Jonesd1049182018-03-28 10:02:20 -07004895 SetRobustLengthParam(length, writeLength);
4896
Geoff Lang0b031062016-10-13 14:30:04 -04004897 return true;
4898}
4899
Geoff Lang0b031062016-10-13 14:30:04 -04004900bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4901 GLuint index,
4902 GLenum pname,
4903 GLsizei bufSize,
4904 GLsizei *length,
4905 GLint *params)
4906{
4907 if (!ValidateRobustEntryPoint(context, bufSize))
4908 {
4909 return false;
4910 }
4911
Brandon Jonesd1049182018-03-28 10:02:20 -07004912 GLsizei writeLength = 0;
4913
4914 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004915 {
4916 return false;
4917 }
4918
Brandon Jonesd1049182018-03-28 10:02:20 -07004919 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004920 {
4921 return false;
4922 }
4923
Brandon Jonesd1049182018-03-28 10:02:20 -07004924 SetRobustLengthParam(length, writeLength);
4925
Geoff Lang0b031062016-10-13 14:30:04 -04004926 return true;
4927}
4928
Geoff Lang0b031062016-10-13 14:30:04 -04004929bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4930 GLuint index,
4931 GLenum pname,
4932 GLsizei bufSize,
4933 GLsizei *length,
4934 GLuint *params)
4935{
4936 if (!ValidateRobustEntryPoint(context, bufSize))
4937 {
4938 return false;
4939 }
4940
Brandon Jonesd1049182018-03-28 10:02:20 -07004941 GLsizei writeLength = 0;
4942
4943 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004944 {
4945 return false;
4946 }
4947
Brandon Jonesd1049182018-03-28 10:02:20 -07004948 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004949 {
4950 return false;
4951 }
4952
Brandon Jonesd1049182018-03-28 10:02:20 -07004953 SetRobustLengthParam(length, writeLength);
4954
Geoff Lang0b031062016-10-13 14:30:04 -04004955 return true;
4956}
4957
Geoff Lang6899b872016-10-14 11:30:13 -04004958bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4959 GLuint program,
4960 GLuint uniformBlockIndex,
4961 GLenum pname,
4962 GLsizei bufSize,
4963 GLsizei *length,
4964 GLint *params)
4965{
4966 if (!ValidateRobustEntryPoint(context, bufSize))
4967 {
4968 return false;
4969 }
4970
Brandon Jonesd1049182018-03-28 10:02:20 -07004971 GLsizei writeLength = 0;
4972
4973 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4974 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004975 {
4976 return false;
4977 }
4978
Brandon Jonesd1049182018-03-28 10:02:20 -07004979 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004980 {
4981 return false;
4982 }
4983
Brandon Jonesd1049182018-03-28 10:02:20 -07004984 SetRobustLengthParam(length, writeLength);
4985
Geoff Lang6899b872016-10-14 11:30:13 -04004986 return true;
4987}
4988
Brandon Jones416aaf92018-04-10 08:10:16 -07004989bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004990 GLenum target,
4991 GLenum internalformat,
4992 GLenum pname,
4993 GLsizei bufSize,
4994 GLsizei *length,
4995 GLint *params)
4996{
4997 if (!ValidateRobustEntryPoint(context, bufSize))
4998 {
4999 return false;
5000 }
5001
Brandon Jonesd1049182018-03-28 10:02:20 -07005002 GLsizei numParams = 0;
5003
5004 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5005 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005006 {
5007 return false;
5008 }
5009
Brandon Jonesd1049182018-03-28 10:02:20 -07005010 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005011 {
5012 return false;
5013 }
5014
Brandon Jonesd1049182018-03-28 10:02:20 -07005015 SetRobustLengthParam(length, numParams);
5016
Geoff Lang0a9661f2016-10-20 10:59:20 -07005017 return true;
5018}
5019
Jamie Madill5b772312018-03-08 20:28:32 -05005020bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005021 GLuint attribIndex,
5022 GLint size,
5023 GLenum type,
5024 GLboolean pureInteger)
5025{
5026 const Caps &caps = context->getCaps();
5027 if (attribIndex >= caps.maxVertexAttributes)
5028 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005029 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005030 return false;
5031 }
5032
5033 if (size < 1 || size > 4)
5034 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005035 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005036 return false;
Shao80957d92017-02-20 21:25:59 +08005037 }
5038
5039 switch (type)
5040 {
5041 case GL_BYTE:
5042 case GL_UNSIGNED_BYTE:
5043 case GL_SHORT:
5044 case GL_UNSIGNED_SHORT:
5045 break;
5046
5047 case GL_INT:
5048 case GL_UNSIGNED_INT:
5049 if (context->getClientMajorVersion() < 3)
5050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005051 context->handleError(InvalidEnum()
5052 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005053 return false;
5054 }
5055 break;
5056
5057 case GL_FIXED:
5058 case GL_FLOAT:
5059 if (pureInteger)
5060 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005061 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005062 return false;
5063 }
5064 break;
5065
5066 case GL_HALF_FLOAT:
5067 if (context->getClientMajorVersion() < 3)
5068 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005069 context->handleError(InvalidEnum()
5070 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005071 return false;
5072 }
5073 if (pureInteger)
5074 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005075 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005076 return false;
5077 }
5078 break;
5079
5080 case GL_INT_2_10_10_10_REV:
5081 case GL_UNSIGNED_INT_2_10_10_10_REV:
5082 if (context->getClientMajorVersion() < 3)
5083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005084 context->handleError(InvalidEnum()
5085 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005086 return false;
5087 }
5088 if (pureInteger)
5089 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005090 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005091 return false;
5092 }
5093 if (size != 4)
5094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005095 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5096 "UNSIGNED_INT_2_10_10_10_REV and "
5097 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005098 return false;
5099 }
5100 break;
5101
5102 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005103 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005104 return false;
5105 }
5106
5107 return true;
5108}
5109
Geoff Lang76e65652017-03-27 14:58:02 -04005110// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5111// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5112// specified clear value and the type of a buffer that is being cleared generates an
5113// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005114bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005115 GLint drawbuffer,
5116 const GLenum *validComponentTypes,
5117 size_t validComponentTypeCount)
5118{
5119 const FramebufferAttachment *attachment =
5120 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5121 if (attachment)
5122 {
5123 GLenum componentType = attachment->getFormat().info->componentType;
5124 const GLenum *end = validComponentTypes + validComponentTypeCount;
5125 if (std::find(validComponentTypes, end, componentType) == end)
5126 {
5127 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005128 InvalidOperation()
5129 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005130 return false;
5131 }
5132 }
5133
5134 return true;
5135}
5136
Jamie Madill5b772312018-03-08 20:28:32 -05005137bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005138{
5139 if (!ValidateRobustEntryPoint(context, dataSize))
5140 {
5141 return false;
5142 }
5143
Jamie Madill43da7c42018-08-01 11:34:49 -04005144 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005145 if (pixelUnpackBuffer == nullptr)
5146 {
5147 if (dataSize < imageSize)
5148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005149 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005150 }
5151 }
5152 return true;
5153}
5154
Jamie Madill5b772312018-03-08 20:28:32 -05005155bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005156 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005157 GLenum pname,
5158 bool pointerVersion,
5159 GLsizei *numParams)
5160{
5161 if (numParams)
5162 {
5163 *numParams = 0;
5164 }
5165
Corentin Walleze4477002017-12-01 14:39:58 -05005166 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005169 return false;
5170 }
5171
5172 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5173 if (!buffer)
5174 {
5175 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005176 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005177 return false;
5178 }
5179
5180 const Extensions &extensions = context->getExtensions();
5181
5182 switch (pname)
5183 {
5184 case GL_BUFFER_USAGE:
5185 case GL_BUFFER_SIZE:
5186 break;
5187
5188 case GL_BUFFER_ACCESS_OES:
5189 if (!extensions.mapBuffer)
5190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005191 context->handleError(InvalidEnum()
5192 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005193 return false;
5194 }
5195 break;
5196
5197 case GL_BUFFER_MAPPED:
5198 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5199 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5200 !extensions.mapBufferRange)
5201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005202 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5203 "GL_OES_mapbuffer or "
5204 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005205 return false;
5206 }
5207 break;
5208
5209 case GL_BUFFER_MAP_POINTER:
5210 if (!pointerVersion)
5211 {
5212 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005213 InvalidEnum()
5214 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005215 return false;
5216 }
5217 break;
5218
5219 case GL_BUFFER_ACCESS_FLAGS:
5220 case GL_BUFFER_MAP_OFFSET:
5221 case GL_BUFFER_MAP_LENGTH:
5222 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005224 context->handleError(InvalidEnum()
5225 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005226 return false;
5227 }
5228 break;
5229
5230 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005231 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005232 return false;
5233 }
5234
5235 // All buffer parameter queries return one value.
5236 if (numParams)
5237 {
5238 *numParams = 1;
5239 }
5240
5241 return true;
5242}
5243
5244bool ValidateGetRenderbufferParameterivBase(Context *context,
5245 GLenum target,
5246 GLenum pname,
5247 GLsizei *length)
5248{
5249 if (length)
5250 {
5251 *length = 0;
5252 }
5253
5254 if (target != GL_RENDERBUFFER)
5255 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005256 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005257 return false;
5258 }
5259
5260 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5261 if (renderbuffer == nullptr)
5262 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005264 return false;
5265 }
5266
5267 switch (pname)
5268 {
5269 case GL_RENDERBUFFER_WIDTH:
5270 case GL_RENDERBUFFER_HEIGHT:
5271 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5272 case GL_RENDERBUFFER_RED_SIZE:
5273 case GL_RENDERBUFFER_GREEN_SIZE:
5274 case GL_RENDERBUFFER_BLUE_SIZE:
5275 case GL_RENDERBUFFER_ALPHA_SIZE:
5276 case GL_RENDERBUFFER_DEPTH_SIZE:
5277 case GL_RENDERBUFFER_STENCIL_SIZE:
5278 break;
5279
5280 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5281 if (!context->getExtensions().framebufferMultisample)
5282 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005283 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005284 return false;
5285 }
5286 break;
5287
5288 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005289 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005290 return false;
5291 }
5292
5293 if (length)
5294 {
5295 *length = 1;
5296 }
5297 return true;
5298}
5299
5300bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5301{
5302 if (length)
5303 {
5304 *length = 0;
5305 }
5306
5307 if (GetValidShader(context, shader) == nullptr)
5308 {
5309 return false;
5310 }
5311
5312 switch (pname)
5313 {
5314 case GL_SHADER_TYPE:
5315 case GL_DELETE_STATUS:
5316 case GL_COMPILE_STATUS:
5317 case GL_INFO_LOG_LENGTH:
5318 case GL_SHADER_SOURCE_LENGTH:
5319 break;
5320
5321 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5322 if (!context->getExtensions().translatedShaderSource)
5323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005324 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 return false;
5326 }
5327 break;
5328
5329 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005330 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005331 return false;
5332 }
5333
5334 if (length)
5335 {
5336 *length = 1;
5337 }
5338 return true;
5339}
5340
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005341bool ValidateGetTexParameterBase(Context *context,
5342 TextureType target,
5343 GLenum pname,
5344 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005345{
5346 if (length)
5347 {
5348 *length = 0;
5349 }
5350
5351 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5352 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005353 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005354 return false;
5355 }
5356
5357 if (context->getTargetTexture(target) == nullptr)
5358 {
5359 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 return false;
5362 }
5363
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005364 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5365 {
5366 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5367 return false;
5368 }
5369
Jamie Madillbe849e42017-05-02 15:49:00 -04005370 switch (pname)
5371 {
5372 case GL_TEXTURE_MAG_FILTER:
5373 case GL_TEXTURE_MIN_FILTER:
5374 case GL_TEXTURE_WRAP_S:
5375 case GL_TEXTURE_WRAP_T:
5376 break;
5377
5378 case GL_TEXTURE_USAGE_ANGLE:
5379 if (!context->getExtensions().textureUsage)
5380 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005381 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005382 return false;
5383 }
5384 break;
5385
5386 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005387 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005388 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005389 return false;
5390 }
5391 break;
5392
5393 case GL_TEXTURE_IMMUTABLE_FORMAT:
5394 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5395 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005397 return false;
5398 }
5399 break;
5400
5401 case GL_TEXTURE_WRAP_R:
5402 case GL_TEXTURE_IMMUTABLE_LEVELS:
5403 case GL_TEXTURE_SWIZZLE_R:
5404 case GL_TEXTURE_SWIZZLE_G:
5405 case GL_TEXTURE_SWIZZLE_B:
5406 case GL_TEXTURE_SWIZZLE_A:
5407 case GL_TEXTURE_BASE_LEVEL:
5408 case GL_TEXTURE_MAX_LEVEL:
5409 case GL_TEXTURE_MIN_LOD:
5410 case GL_TEXTURE_MAX_LOD:
5411 case GL_TEXTURE_COMPARE_MODE:
5412 case GL_TEXTURE_COMPARE_FUNC:
5413 if (context->getClientMajorVersion() < 3)
5414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005415 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005416 return false;
5417 }
5418 break;
5419
5420 case GL_TEXTURE_SRGB_DECODE_EXT:
5421 if (!context->getExtensions().textureSRGBDecode)
5422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005423 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005424 return false;
5425 }
5426 break;
5427
Yunchao Hebacaa712018-01-30 14:01:39 +08005428 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5429 if (context->getClientVersion() < Version(3, 1))
5430 {
5431 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5432 return false;
5433 }
5434 break;
5435
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005436 case GL_GENERATE_MIPMAP:
5437 case GL_TEXTURE_CROP_RECT_OES:
5438 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5439 // after GL_OES_draw_texture functionality implemented
5440 if (context->getClientMajorVersion() > 1)
5441 {
5442 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5443 return false;
5444 }
5445 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005447 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005448 return false;
5449 }
5450
5451 if (length)
5452 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005453 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005454 }
5455 return true;
5456}
5457
5458bool ValidateGetVertexAttribBase(Context *context,
5459 GLuint index,
5460 GLenum pname,
5461 GLsizei *length,
5462 bool pointer,
5463 bool pureIntegerEntryPoint)
5464{
5465 if (length)
5466 {
5467 *length = 0;
5468 }
5469
5470 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005472 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005473 return false;
5474 }
5475
5476 if (index >= context->getCaps().maxVertexAttributes)
5477 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005478 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005479 return false;
5480 }
5481
5482 if (pointer)
5483 {
5484 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5485 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005486 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005487 return false;
5488 }
5489 }
5490 else
5491 {
5492 switch (pname)
5493 {
5494 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5495 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5496 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5497 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5498 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5499 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5500 case GL_CURRENT_VERTEX_ATTRIB:
5501 break;
5502
5503 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5504 static_assert(
5505 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5506 "ANGLE extension enums not equal to GL enums.");
5507 if (context->getClientMajorVersion() < 3 &&
5508 !context->getExtensions().instancedArrays)
5509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005510 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5511 "requires OpenGL ES 3.0 or "
5512 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005513 return false;
5514 }
5515 break;
5516
5517 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5518 if (context->getClientMajorVersion() < 3)
5519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005520 context->handleError(
5521 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005522 return false;
5523 }
5524 break;
5525
5526 case GL_VERTEX_ATTRIB_BINDING:
5527 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5528 if (context->getClientVersion() < ES_3_1)
5529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005530 context->handleError(InvalidEnum()
5531 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005532 return false;
5533 }
5534 break;
5535
5536 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005537 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005538 return false;
5539 }
5540 }
5541
5542 if (length)
5543 {
5544 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5545 {
5546 *length = 4;
5547 }
5548 else
5549 {
5550 *length = 1;
5551 }
5552 }
5553
5554 return true;
5555}
5556
Jamie Madill4928b7c2017-06-20 12:57:39 -04005557bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005558 GLint x,
5559 GLint y,
5560 GLsizei width,
5561 GLsizei height,
5562 GLenum format,
5563 GLenum type,
5564 GLsizei bufSize,
5565 GLsizei *length,
5566 GLsizei *columns,
5567 GLsizei *rows,
5568 void *pixels)
5569{
5570 if (length != nullptr)
5571 {
5572 *length = 0;
5573 }
5574 if (rows != nullptr)
5575 {
5576 *rows = 0;
5577 }
5578 if (columns != nullptr)
5579 {
5580 *columns = 0;
5581 }
5582
5583 if (width < 0 || height < 0)
5584 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005585 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 return false;
5587 }
5588
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005589 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005590
Jamie Madill427064d2018-04-13 16:20:34 -04005591 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005592 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005593 return false;
5594 }
5595
Jamie Madille98b1b52018-03-08 09:47:23 -05005596 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005597 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005598 return false;
5599 }
5600
Jamie Madill690c8eb2018-03-12 15:20:03 -04005601 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005602 ASSERT(framebuffer);
5603
5604 if (framebuffer->getReadBufferState() == GL_NONE)
5605 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005606 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005607 return false;
5608 }
5609
5610 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5611 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5612 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5613 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5614 // situation is an application error that would lead to a crash in ANGLE.
5615 if (readBuffer == nullptr)
5616 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005617 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005618 return false;
5619 }
5620
Martin Radev28031682017-07-28 14:47:56 +03005621 // ANGLE_multiview, Revision 1:
5622 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005623 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5624 // in the current read framebuffer is more than one.
5625 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005626 {
5627 context->handleError(InvalidFramebufferOperation()
5628 << "Attempting to read from a multi-view framebuffer.");
5629 return false;
5630 }
5631
Geoff Lang280ba992017-04-18 16:30:58 -04005632 if (context->getExtensions().webglCompatibility)
5633 {
5634 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5635 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5636 // and type before validating the combination of format and type. However, the
5637 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5638 // verifies that GL_INVALID_OPERATION is generated.
5639 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5640 // dEQP/WebGL.
5641 if (!ValidReadPixelsFormatEnum(context, format))
5642 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005643 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005644 return false;
5645 }
5646
5647 if (!ValidReadPixelsTypeEnum(context, type))
5648 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005649 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005650 return false;
5651 }
5652 }
5653
Jamie Madill690c8eb2018-03-12 15:20:03 -04005654 GLenum currentFormat = GL_NONE;
5655 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5656
5657 GLenum currentType = GL_NONE;
5658 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5659
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5661
5662 bool validFormatTypeCombination =
5663 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5664
5665 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5666 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005668 return false;
5669 }
5670
5671 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005672 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005673 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5674 {
5675 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005676 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005677 return false;
5678 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005679 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5680 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5681 {
5682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5683 return false;
5684 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005685
5686 // .. the data would be packed to the buffer object such that the memory writes required
5687 // would exceed the data store size.
5688 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005689 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005690 const auto &pack = context->getGLState().getPackState();
5691
Jamie Madillca2ff382018-07-11 09:01:17 -04005692 GLuint endByte = 0;
5693 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005694 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005695 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005696 return false;
5697 }
5698
Jamie Madillbe849e42017-05-02 15:49:00 -04005699 if (bufSize >= 0)
5700 {
5701 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5702 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005703 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005704 return false;
5705 }
5706 }
5707
5708 if (pixelPackBuffer != nullptr)
5709 {
5710 CheckedNumeric<size_t> checkedEndByte(endByte);
5711 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5712 checkedEndByte += checkedOffset;
5713
5714 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5715 {
5716 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005717 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005718 return false;
5719 }
5720 }
5721
5722 if (pixelPackBuffer == nullptr && length != nullptr)
5723 {
5724 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5725 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005727 return false;
5728 }
5729
5730 *length = static_cast<GLsizei>(endByte);
5731 }
5732
Geoff Langa953b522018-02-21 16:56:23 -05005733 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005734 angle::CheckedNumeric<int> clippedExtent(length);
5735 if (start < 0)
5736 {
5737 // "subtract" the area that is less than 0
5738 clippedExtent += start;
5739 }
5740
Geoff Langa953b522018-02-21 16:56:23 -05005741 angle::CheckedNumeric<int> readExtent = start;
5742 readExtent += length;
5743 if (!readExtent.IsValid())
5744 {
5745 return false;
5746 }
5747
5748 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005749 {
5750 // Subtract the region to the right of the read buffer
5751 clippedExtent -= (readExtent - bufferSize);
5752 }
5753
5754 if (!clippedExtent.IsValid())
5755 {
Geoff Langa953b522018-02-21 16:56:23 -05005756 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005757 }
5758
Geoff Langa953b522018-02-21 16:56:23 -05005759 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5760 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005761 };
5762
Geoff Langa953b522018-02-21 16:56:23 -05005763 GLsizei writtenColumns = 0;
5764 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5765 {
5766 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5767 return false;
5768 }
5769
5770 GLsizei writtenRows = 0;
5771 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5772 {
5773 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5774 return false;
5775 }
5776
Jamie Madillbe849e42017-05-02 15:49:00 -04005777 if (columns != nullptr)
5778 {
Geoff Langa953b522018-02-21 16:56:23 -05005779 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005780 }
5781
5782 if (rows != nullptr)
5783 {
Geoff Langa953b522018-02-21 16:56:23 -05005784 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005785 }
5786
5787 return true;
5788}
5789
5790template <typename ParamType>
5791bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005792 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005793 GLenum pname,
5794 GLsizei bufSize,
5795 const ParamType *params)
5796{
5797 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5798 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005799 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005800 return false;
5801 }
5802
5803 if (context->getTargetTexture(target) == nullptr)
5804 {
5805 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005806 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 return false;
5808 }
5809
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005810 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005811 if (bufSize >= 0 && bufSize < minBufSize)
5812 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005813 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005814 return false;
5815 }
5816
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005817 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5818 {
5819 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5820 return false;
5821 }
5822
Jamie Madillbe849e42017-05-02 15:49:00 -04005823 switch (pname)
5824 {
5825 case GL_TEXTURE_WRAP_R:
5826 case GL_TEXTURE_SWIZZLE_R:
5827 case GL_TEXTURE_SWIZZLE_G:
5828 case GL_TEXTURE_SWIZZLE_B:
5829 case GL_TEXTURE_SWIZZLE_A:
5830 case GL_TEXTURE_BASE_LEVEL:
5831 case GL_TEXTURE_MAX_LEVEL:
5832 case GL_TEXTURE_COMPARE_MODE:
5833 case GL_TEXTURE_COMPARE_FUNC:
5834 case GL_TEXTURE_MIN_LOD:
5835 case GL_TEXTURE_MAX_LOD:
5836 if (context->getClientMajorVersion() < 3)
5837 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005838 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005839 return false;
5840 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005841 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005843 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5844 "available without "
5845 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005846 return false;
5847 }
5848 break;
5849
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005850 case GL_GENERATE_MIPMAP:
5851 case GL_TEXTURE_CROP_RECT_OES:
5852 if (context->getClientMajorVersion() > 1)
5853 {
5854 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5855 return false;
5856 }
5857 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005858 default:
5859 break;
5860 }
5861
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005862 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005863 {
5864 switch (pname)
5865 {
5866 case GL_TEXTURE_MIN_FILTER:
5867 case GL_TEXTURE_MAG_FILTER:
5868 case GL_TEXTURE_WRAP_S:
5869 case GL_TEXTURE_WRAP_T:
5870 case GL_TEXTURE_WRAP_R:
5871 case GL_TEXTURE_MIN_LOD:
5872 case GL_TEXTURE_MAX_LOD:
5873 case GL_TEXTURE_COMPARE_MODE:
5874 case GL_TEXTURE_COMPARE_FUNC:
5875 context->handleError(InvalidEnum()
5876 << "Invalid parameter for 2D multisampled textures.");
5877 return false;
5878 }
5879 }
5880
Jamie Madillbe849e42017-05-02 15:49:00 -04005881 switch (pname)
5882 {
5883 case GL_TEXTURE_WRAP_S:
5884 case GL_TEXTURE_WRAP_T:
5885 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005886 {
5887 bool restrictedWrapModes =
5888 target == TextureType::External || target == TextureType::Rectangle;
5889 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005890 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005891 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005892 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005893 }
5894 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005895
5896 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005897 {
5898 bool restrictedMinFilter =
5899 target == TextureType::External || target == TextureType::Rectangle;
5900 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005901 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005902 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005903 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005904 }
5905 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005906
5907 case GL_TEXTURE_MAG_FILTER:
5908 if (!ValidateTextureMagFilterValue(context, params))
5909 {
5910 return false;
5911 }
5912 break;
5913
5914 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005915 if (!context->getExtensions().textureUsage)
5916 {
5917 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5918 return false;
5919 }
5920
Jamie Madillbe849e42017-05-02 15:49:00 -04005921 switch (ConvertToGLenum(params[0]))
5922 {
5923 case GL_NONE:
5924 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5925 break;
5926
5927 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005928 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005929 return false;
5930 }
5931 break;
5932
5933 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005934 {
5935 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5936 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005937 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005938 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005939 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005940 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5941 }
5942 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005943
5944 case GL_TEXTURE_MIN_LOD:
5945 case GL_TEXTURE_MAX_LOD:
5946 // any value is permissible
5947 break;
5948
5949 case GL_TEXTURE_COMPARE_MODE:
5950 if (!ValidateTextureCompareModeValue(context, params))
5951 {
5952 return false;
5953 }
5954 break;
5955
5956 case GL_TEXTURE_COMPARE_FUNC:
5957 if (!ValidateTextureCompareFuncValue(context, params))
5958 {
5959 return false;
5960 }
5961 break;
5962
5963 case GL_TEXTURE_SWIZZLE_R:
5964 case GL_TEXTURE_SWIZZLE_G:
5965 case GL_TEXTURE_SWIZZLE_B:
5966 case GL_TEXTURE_SWIZZLE_A:
5967 switch (ConvertToGLenum(params[0]))
5968 {
5969 case GL_RED:
5970 case GL_GREEN:
5971 case GL_BLUE:
5972 case GL_ALPHA:
5973 case GL_ZERO:
5974 case GL_ONE:
5975 break;
5976
5977 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005978 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005979 return false;
5980 }
5981 break;
5982
5983 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005984 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005986 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005987 return false;
5988 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005989 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005991 context->handleError(InvalidOperation()
5992 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005993 return false;
5994 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005995 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005996 {
5997 context->handleError(InvalidOperation()
5998 << "Base level must be 0 for multisampled textures.");
5999 return false;
6000 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006001 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006002 {
6003 context->handleError(InvalidOperation()
6004 << "Base level must be 0 for rectangle textures.");
6005 return false;
6006 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006007 break;
6008
6009 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006010 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006011 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006012 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006013 return false;
6014 }
6015 break;
6016
6017 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6018 if (context->getClientVersion() < Version(3, 1))
6019 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006020 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006021 return false;
6022 }
6023 switch (ConvertToGLenum(params[0]))
6024 {
6025 case GL_DEPTH_COMPONENT:
6026 case GL_STENCIL_INDEX:
6027 break;
6028
6029 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006030 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006031 return false;
6032 }
6033 break;
6034
6035 case GL_TEXTURE_SRGB_DECODE_EXT:
6036 if (!ValidateTextureSRGBDecodeValue(context, params))
6037 {
6038 return false;
6039 }
6040 break;
6041
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006042 case GL_GENERATE_MIPMAP:
6043 case GL_TEXTURE_CROP_RECT_OES:
6044 if (context->getClientMajorVersion() > 1)
6045 {
6046 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6047 return false;
6048 }
6049 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006050 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006052 return false;
6053 }
6054
6055 return true;
6056}
6057
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006058template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6059template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006060
Jamie Madill5b772312018-03-08 20:28:32 -05006061bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006062{
6063 if (index >= MAX_VERTEX_ATTRIBS)
6064 {
6065 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6066 return false;
6067 }
6068
6069 return true;
6070}
6071
6072bool ValidateGetActiveUniformBlockivBase(Context *context,
6073 GLuint program,
6074 GLuint uniformBlockIndex,
6075 GLenum pname,
6076 GLsizei *length)
6077{
6078 if (length)
6079 {
6080 *length = 0;
6081 }
6082
6083 if (context->getClientMajorVersion() < 3)
6084 {
6085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6086 return false;
6087 }
6088
6089 Program *programObject = GetValidProgram(context, program);
6090 if (!programObject)
6091 {
6092 return false;
6093 }
6094
6095 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6096 {
6097 context->handleError(InvalidValue()
6098 << "uniformBlockIndex exceeds active uniform block count.");
6099 return false;
6100 }
6101
6102 switch (pname)
6103 {
6104 case GL_UNIFORM_BLOCK_BINDING:
6105 case GL_UNIFORM_BLOCK_DATA_SIZE:
6106 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6107 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6108 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6109 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6110 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6111 break;
6112
6113 default:
6114 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6115 return false;
6116 }
6117
6118 if (length)
6119 {
6120 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6121 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006122 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006123 programObject->getUniformBlockByIndex(uniformBlockIndex);
6124 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6125 }
6126 else
6127 {
6128 *length = 1;
6129 }
6130 }
6131
6132 return true;
6133}
6134
Jamie Madill9696d072017-08-26 23:19:57 -04006135template <typename ParamType>
6136bool ValidateSamplerParameterBase(Context *context,
6137 GLuint sampler,
6138 GLenum pname,
6139 GLsizei bufSize,
6140 ParamType *params)
6141{
6142 if (context->getClientMajorVersion() < 3)
6143 {
6144 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6145 return false;
6146 }
6147
6148 if (!context->isSampler(sampler))
6149 {
6150 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6151 return false;
6152 }
6153
6154 const GLsizei minBufSize = 1;
6155 if (bufSize >= 0 && bufSize < minBufSize)
6156 {
6157 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6158 return false;
6159 }
6160
6161 switch (pname)
6162 {
6163 case GL_TEXTURE_WRAP_S:
6164 case GL_TEXTURE_WRAP_T:
6165 case GL_TEXTURE_WRAP_R:
6166 if (!ValidateTextureWrapModeValue(context, params, false))
6167 {
6168 return false;
6169 }
6170 break;
6171
6172 case GL_TEXTURE_MIN_FILTER:
6173 if (!ValidateTextureMinFilterValue(context, params, false))
6174 {
6175 return false;
6176 }
6177 break;
6178
6179 case GL_TEXTURE_MAG_FILTER:
6180 if (!ValidateTextureMagFilterValue(context, params))
6181 {
6182 return false;
6183 }
6184 break;
6185
6186 case GL_TEXTURE_MIN_LOD:
6187 case GL_TEXTURE_MAX_LOD:
6188 // any value is permissible
6189 break;
6190
6191 case GL_TEXTURE_COMPARE_MODE:
6192 if (!ValidateTextureCompareModeValue(context, params))
6193 {
6194 return false;
6195 }
6196 break;
6197
6198 case GL_TEXTURE_COMPARE_FUNC:
6199 if (!ValidateTextureCompareFuncValue(context, params))
6200 {
6201 return false;
6202 }
6203 break;
6204
6205 case GL_TEXTURE_SRGB_DECODE_EXT:
6206 if (!ValidateTextureSRGBDecodeValue(context, params))
6207 {
6208 return false;
6209 }
6210 break;
6211
Luc Ferron1b1a8642018-01-23 15:12:01 -05006212 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6213 {
6214 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6215 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6216 {
6217 return false;
6218 }
6219 }
6220 break;
6221
Jamie Madill9696d072017-08-26 23:19:57 -04006222 default:
6223 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6224 return false;
6225 }
6226
6227 return true;
6228}
6229
6230template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6231template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6232
6233bool ValidateGetSamplerParameterBase(Context *context,
6234 GLuint sampler,
6235 GLenum pname,
6236 GLsizei *length)
6237{
6238 if (length)
6239 {
6240 *length = 0;
6241 }
6242
6243 if (context->getClientMajorVersion() < 3)
6244 {
6245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6246 return false;
6247 }
6248
6249 if (!context->isSampler(sampler))
6250 {
6251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6252 return false;
6253 }
6254
6255 switch (pname)
6256 {
6257 case GL_TEXTURE_WRAP_S:
6258 case GL_TEXTURE_WRAP_T:
6259 case GL_TEXTURE_WRAP_R:
6260 case GL_TEXTURE_MIN_FILTER:
6261 case GL_TEXTURE_MAG_FILTER:
6262 case GL_TEXTURE_MIN_LOD:
6263 case GL_TEXTURE_MAX_LOD:
6264 case GL_TEXTURE_COMPARE_MODE:
6265 case GL_TEXTURE_COMPARE_FUNC:
6266 break;
6267
Luc Ferron1b1a8642018-01-23 15:12:01 -05006268 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6269 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6270 {
6271 return false;
6272 }
6273 break;
6274
Jamie Madill9696d072017-08-26 23:19:57 -04006275 case GL_TEXTURE_SRGB_DECODE_EXT:
6276 if (!context->getExtensions().textureSRGBDecode)
6277 {
6278 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6279 return false;
6280 }
6281 break;
6282
6283 default:
6284 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6285 return false;
6286 }
6287
6288 if (length)
6289 {
6290 *length = 1;
6291 }
6292 return true;
6293}
6294
6295bool ValidateGetInternalFormativBase(Context *context,
6296 GLenum target,
6297 GLenum internalformat,
6298 GLenum pname,
6299 GLsizei bufSize,
6300 GLsizei *numParams)
6301{
6302 if (numParams)
6303 {
6304 *numParams = 0;
6305 }
6306
6307 if (context->getClientMajorVersion() < 3)
6308 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006310 return false;
6311 }
6312
6313 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006314 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006315 {
6316 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6317 return false;
6318 }
6319
6320 switch (target)
6321 {
6322 case GL_RENDERBUFFER:
6323 break;
6324
6325 case GL_TEXTURE_2D_MULTISAMPLE:
6326 if (context->getClientVersion() < ES_3_1)
6327 {
6328 context->handleError(InvalidOperation()
6329 << "Texture target requires at least OpenGL ES 3.1.");
6330 return false;
6331 }
6332 break;
6333
6334 default:
6335 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6336 return false;
6337 }
6338
6339 if (bufSize < 0)
6340 {
6341 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6342 return false;
6343 }
6344
6345 GLsizei maxWriteParams = 0;
6346 switch (pname)
6347 {
6348 case GL_NUM_SAMPLE_COUNTS:
6349 maxWriteParams = 1;
6350 break;
6351
6352 case GL_SAMPLES:
6353 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6354 break;
6355
6356 default:
6357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6358 return false;
6359 }
6360
6361 if (numParams)
6362 {
6363 // glGetInternalFormativ will not overflow bufSize
6364 *numParams = std::min(bufSize, maxWriteParams);
6365 }
6366
6367 return true;
6368}
6369
Jamie Madille98b1b52018-03-08 09:47:23 -05006370bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6371{
Jamie Madill427064d2018-04-13 16:20:34 -04006372 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006373 {
6374 context->handleError(InvalidOperation());
6375 return false;
6376 }
6377 return true;
6378}
6379
Lingfeng Yang038dd532018-03-29 17:31:52 -07006380bool ValidateMultitextureUnit(Context *context, GLenum texture)
6381{
6382 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6383 {
6384 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6385 return false;
6386 }
6387 return true;
6388}
6389
Jamie Madillc29968b2016-01-20 11:17:23 -05006390} // namespace gl