blob: 5e56e73519aeca968cb771faab97d1ad90887447 [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 Madill778bf092018-11-14 09:54:36 -050026#include "libANGLE/validationES2_autogen.h"
27#include "libANGLE/validationES3_autogen.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 Madille0472f32018-11-27 16:32:45 -050036using namespace err;
37
Jamie Madill1ca74672015-07-21 15:14:11 -040038namespace
39{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050040bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
41{
42 // List of compressed format that require that the texture size is smaller than or a multiple of
43 // the compressed block size.
44 switch (internalFormat)
45 {
46 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
47 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
49 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
50 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
52 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
53 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
54 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
55 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
58 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
59 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
60 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Olli Etuahof2ed2992018-10-04 13:54:42 +030061 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
62 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
63 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
64 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
Luc Ferron9dbaeba2018-02-01 07:26:59 -050065 return true;
jchen10a99ed552017-09-22 08:10:32 +080066
Luc Ferron9dbaeba2018-02-01 07:26:59 -050067 default:
68 return false;
69 }
70}
71bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
72{
73 // Compressed sub textures have additional formats that requires exact size.
74 // ES 3.1, Section 8.7, Page 171
75 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
76 IsETC2EACFormat(internalFormat);
77}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030078
79bool DifferenceCanOverflow(GLint a, GLint b)
80{
81 CheckedNumeric<GLint> checkedA(a);
82 checkedA -= b;
83 // Use negation to make sure that the difference can't overflow regardless of the order.
84 checkedA = -checkedA;
85 return !checkedA.IsValid();
86}
87
Jamie Madill16e28fd2018-09-12 11:03:05 -040088bool ValidateDrawAttribsImpl(Context *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040089{
Jamie Madill51af38b2018-04-15 08:50:56 -040090 // If we're drawing zero vertices, we have enough data.
Jamie Madill2da53562018-08-01 11:34:47 -040091 ASSERT(primcount > 0);
Jamie Madill51af38b2018-04-15 08:50:56 -040092
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 {
Jamie Madille0472f32018-11-27 16:32:45 -050099 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400100 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.
Jamie Madille0472f32018-11-27 16:32:45 -0500105 context->validationError(GL_INVALID_OPERATION, kInsufficientVertexBufferSize);
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400106 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400107}
108
Jamie Madill16e28fd2018-09-12 11:03:05 -0400109ANGLE_INLINE bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
110{
111 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
112 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
113 {
114 return true;
115 }
116 else
117 {
118 return ValidateDrawAttribsImpl(context, primcount, maxVertex);
119 }
120}
121
Jamie Madill5b772312018-03-08 20:28:32 -0500122bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400123{
124 switch (type)
125 {
126 // Types referenced in Table 3.4 of the ES 2.0.25 spec
127 case GL_UNSIGNED_BYTE:
128 case GL_UNSIGNED_SHORT_4_4_4_4:
129 case GL_UNSIGNED_SHORT_5_5_5_1:
130 case GL_UNSIGNED_SHORT_5_6_5:
131 return context->getClientVersion() >= ES_2_0;
132
133 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
134 case GL_BYTE:
135 case GL_INT:
136 case GL_SHORT:
137 case GL_UNSIGNED_INT:
138 case GL_UNSIGNED_INT_10F_11F_11F_REV:
139 case GL_UNSIGNED_INT_24_8:
140 case GL_UNSIGNED_INT_2_10_10_10_REV:
141 case GL_UNSIGNED_INT_5_9_9_9_REV:
142 case GL_UNSIGNED_SHORT:
143 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
144 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
145 return context->getClientVersion() >= ES_3_0;
146
147 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400148 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
149 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400150
151 case GL_HALF_FLOAT:
152 return context->getClientVersion() >= ES_3_0 ||
153 context->getExtensions().textureHalfFloat;
154
155 case GL_HALF_FLOAT_OES:
156 return context->getExtensions().colorBufferHalfFloat;
157
158 default:
159 return false;
160 }
161}
162
Jamie Madill5b772312018-03-08 20:28:32 -0500163bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400164{
165 switch (format)
166 {
167 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
168 case GL_RGBA:
169 case GL_RGB:
170 case GL_ALPHA:
171 return context->getClientVersion() >= ES_2_0;
172
173 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
174 case GL_RG:
175 case GL_RED:
176 case GL_RGBA_INTEGER:
177 case GL_RGB_INTEGER:
178 case GL_RG_INTEGER:
179 case GL_RED_INTEGER:
180 return context->getClientVersion() >= ES_3_0;
181
182 case GL_SRGB_ALPHA_EXT:
183 case GL_SRGB_EXT:
184 return context->getExtensions().sRGB;
185
186 case GL_BGRA_EXT:
187 return context->getExtensions().readFormatBGRA;
188
189 default:
190 return false;
191 }
192}
193
Jamie Madill5b772312018-03-08 20:28:32 -0500194bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400195 GLenum framebufferComponentType,
196 GLenum format,
197 GLenum type)
198{
199 switch (framebufferComponentType)
200 {
201 case GL_UNSIGNED_NORMALIZED:
202 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
203 // ReadPixels with BGRA even if the extension is not present
204 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
205 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
206 type == GL_UNSIGNED_BYTE);
207
208 case GL_SIGNED_NORMALIZED:
209 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
210
211 case GL_INT:
212 return (format == GL_RGBA_INTEGER && type == GL_INT);
213
214 case GL_UNSIGNED_INT:
215 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
216
217 case GL_FLOAT:
218 return (format == GL_RGBA && type == GL_FLOAT);
219
220 default:
221 UNREACHABLE();
222 return false;
223 }
224}
225
Geoff Langc1984ed2016-10-07 12:41:00 -0400226template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400227bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400228{
229 switch (ConvertToGLenum(params[0]))
230 {
231 case GL_CLAMP_TO_EDGE:
232 break;
233
Till Rathmannb8543632018-10-02 19:46:14 +0200234 case GL_CLAMP_TO_BORDER:
235 if (!context->getExtensions().textureBorderClamp)
236 {
Jamie Madille0472f32018-11-27 16:32:45 -0500237 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +0200238 return false;
239 }
240 break;
241
Geoff Langc1984ed2016-10-07 12:41:00 -0400242 case GL_REPEAT:
243 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400244 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400245 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400246 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Jamie Madille0472f32018-11-27 16:32:45 -0500247 context->validationError(GL_INVALID_ENUM, kInvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400248 return false;
249 }
250 break;
251
252 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500253 context->validationError(GL_INVALID_ENUM, kInvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400254 return false;
255 }
256
257 return true;
258}
259
260template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400261bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400262{
263 switch (ConvertToGLenum(params[0]))
264 {
265 case GL_NEAREST:
266 case GL_LINEAR:
267 break;
268
269 case GL_NEAREST_MIPMAP_NEAREST:
270 case GL_LINEAR_MIPMAP_NEAREST:
271 case GL_NEAREST_MIPMAP_LINEAR:
272 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400273 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400274 {
275 // OES_EGL_image_external specifies this error.
Jamie Madille0472f32018-11-27 16:32:45 -0500276 context->validationError(GL_INVALID_ENUM, kInvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400277 return false;
278 }
279 break;
280
281 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500282 context->validationError(GL_INVALID_ENUM, kInvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400283 return false;
284 }
285
286 return true;
287}
288
289template <typename ParamType>
290bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
291{
292 switch (ConvertToGLenum(params[0]))
293 {
294 case GL_NEAREST:
295 case GL_LINEAR:
296 break;
297
298 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500299 context->validationError(GL_INVALID_ENUM, kInvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400300 return false;
301 }
302
303 return true;
304}
305
306template <typename ParamType>
307bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
308{
309 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
310 switch (ConvertToGLenum(params[0]))
311 {
312 case GL_NONE:
313 case GL_COMPARE_REF_TO_TEXTURE:
314 break;
315
316 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500317 context->validationError(GL_INVALID_ENUM, kUnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400318 return false;
319 }
320
321 return true;
322}
323
324template <typename ParamType>
325bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
326{
327 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
328 switch (ConvertToGLenum(params[0]))
329 {
330 case GL_LEQUAL:
331 case GL_GEQUAL:
332 case GL_LESS:
333 case GL_GREATER:
334 case GL_EQUAL:
335 case GL_NOTEQUAL:
336 case GL_ALWAYS:
337 case GL_NEVER:
338 break;
339
340 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500341 context->validationError(GL_INVALID_ENUM, kUnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400342 return false;
343 }
344
345 return true;
346}
347
348template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700349bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
350{
351 if (!context->getExtensions().textureSRGBDecode)
352 {
Jamie Madille0472f32018-11-27 16:32:45 -0500353 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700354 return false;
355 }
356
357 switch (ConvertToGLenum(params[0]))
358 {
359 case GL_DECODE_EXT:
360 case GL_SKIP_DECODE_EXT:
361 break;
362
363 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500364 context->validationError(GL_INVALID_ENUM, kUnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700365 return false;
366 }
367
368 return true;
369}
370
Luc Ferron1b1a8642018-01-23 15:12:01 -0500371bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
372{
373 if (!context->getExtensions().textureFilterAnisotropic)
374 {
Jamie Madille0472f32018-11-27 16:32:45 -0500375 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Luc Ferron1b1a8642018-01-23 15:12:01 -0500376 return false;
377 }
378
379 return true;
380}
381
382bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
383{
384 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
385 {
386 return false;
387 }
388
389 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
390
391 if (paramValue < 1 || paramValue > largest)
392 {
Jamie Madille0472f32018-11-27 16:32:45 -0500393 context->validationError(GL_INVALID_VALUE, kOutsideOfBounds);
Luc Ferron1b1a8642018-01-23 15:12:01 -0500394 return false;
395 }
396
397 return true;
398}
399
Jamie Madill5b772312018-03-08 20:28:32 -0500400bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400401{
Jamie Madill785e8a02018-10-04 17:42:00 -0400402 const Program *program = context->getGLState().getLinkedProgram(context);
Geoff Lange0cff192017-05-30 13:04:56 -0400403 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
404
Jamie Madille7d80f32018-08-08 15:49:23 -0400405 return ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
406 framebuffer->getDrawBufferTypeMask().to_ulong(),
407 program->getActiveOutputVariables().to_ulong(),
408 framebuffer->getDrawBufferMask().to_ulong());
Geoff Lange0cff192017-05-30 13:04:56 -0400409}
410
Jamie Madill5b772312018-03-08 20:28:32 -0500411bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400412{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700413 const auto &glState = context->getGLState();
Jamie Madill785e8a02018-10-04 17:42:00 -0400414 const Program *program = context->getGLState().getLinkedProgram(context);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400415 const VertexArray *vao = context->getGLState().getVertexArray();
416
Brandon Jonesc405ae72017-12-06 14:15:03 -0800417 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
418 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
419 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
420
421 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
422 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
423 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
424
Jamie Madille7d80f32018-08-08 15:49:23 -0400425 return ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(),
426 vaoAttribTypeBits, program->getAttributesMask().to_ulong(),
427 0xFFFF);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400428}
429
Jamie Madill493f9572018-05-24 19:52:15 -0400430bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
431 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800432{
433 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400434 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800435 {
Jamie Madill493f9572018-05-24 19:52:15 -0400436 case PrimitiveMode::Points:
437 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
438 case PrimitiveMode::Lines:
439 case PrimitiveMode::LineStrip:
440 case PrimitiveMode::LineLoop:
441 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
442 case PrimitiveMode::LinesAdjacency:
443 case PrimitiveMode::LineStripAdjacency:
444 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
445 case PrimitiveMode::Triangles:
446 case PrimitiveMode::TriangleFan:
447 case PrimitiveMode::TriangleStrip:
448 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
449 case PrimitiveMode::TrianglesAdjacency:
450 case PrimitiveMode::TriangleStripAdjacency:
451 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800452 default:
453 UNREACHABLE();
454 return false;
455 }
456}
457
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700458// GLES1 texture parameters are a small subset of the others
459bool IsValidGLES1TextureParameter(GLenum pname)
460{
461 switch (pname)
462 {
463 case GL_TEXTURE_MAG_FILTER:
464 case GL_TEXTURE_MIN_FILTER:
465 case GL_TEXTURE_WRAP_S:
466 case GL_TEXTURE_WRAP_T:
467 case GL_TEXTURE_WRAP_R:
468 case GL_GENERATE_MIPMAP:
469 case GL_TEXTURE_CROP_RECT_OES:
470 return true;
471 default:
472 return false;
473 }
474}
Till Rathmannb8543632018-10-02 19:46:14 +0200475
476unsigned int GetSamplerParameterCount(GLenum pname)
477{
478 return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1;
479}
480
Geoff Langf41a7152016-09-19 15:11:17 -0400481} // anonymous namespace
482
Brandon Jonesd1049182018-03-28 10:02:20 -0700483void SetRobustLengthParam(GLsizei *length, GLsizei value)
484{
485 if (length)
486 {
487 *length = value;
488 }
489}
490
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500491bool IsETC2EACFormat(const GLenum format)
492{
493 // ES 3.1, Table 8.19
494 switch (format)
495 {
496 case GL_COMPRESSED_R11_EAC:
497 case GL_COMPRESSED_SIGNED_R11_EAC:
498 case GL_COMPRESSED_RG11_EAC:
499 case GL_COMPRESSED_SIGNED_RG11_EAC:
500 case GL_COMPRESSED_RGB8_ETC2:
501 case GL_COMPRESSED_SRGB8_ETC2:
502 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
503 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
504 case GL_COMPRESSED_RGBA8_ETC2_EAC:
505 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
506 return true;
507
508 default:
509 return false;
510 }
511}
512
Jamie Madill5b772312018-03-08 20:28:32 -0500513bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400514{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800515 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400516 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800517 case TextureType::_2D:
518 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800519 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400520
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800521 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400522 return context->getExtensions().textureRectangle;
523
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800524 case TextureType::_3D:
525 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800526 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500527
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800528 case TextureType::_2DMultisample:
Yizhou Jiang7818a852018-09-06 15:02:04 +0800529 return (context->getClientVersion() >= Version(3, 1) ||
530 context->getExtensions().textureMultisample);
Olli Etuahod310a432018-08-24 15:40:23 +0300531 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300532 return context->getExtensions().textureStorageMultisample2DArray;
Geoff Lang3b573612016-10-31 14:08:10 -0400533
He Yunchaoced53ae2016-11-29 15:00:51 +0800534 default:
535 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500536 }
Jamie Madill35d15012013-10-07 10:46:37 -0400537}
538
Jamie Madill5b772312018-03-08 20:28:32 -0500539bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500540{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800541 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500542 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800543 case TextureType::_2D:
544 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500545 return true;
546
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800547 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400548 return context->getExtensions().textureRectangle;
549
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500550 default:
551 return false;
552 }
553}
554
Jamie Madill5b772312018-03-08 20:28:32 -0500555bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500556{
557 switch (target)
558 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800559 case TextureType::_3D:
560 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300561 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500562
563 default:
564 return false;
565 }
566}
567
Ian Ewellbda75592016-04-18 17:25:54 -0400568// Most texture GL calls are not compatible with external textures, so we have a separate validation
569// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500570bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400571{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800572 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400573 (context->getExtensions().eglImageExternal ||
574 context->getExtensions().eglStreamConsumerExternal);
575}
576
Shannon Woods4dfed832014-03-17 20:03:39 -0400577// This function differs from ValidTextureTarget in that the target must be
578// usable as the destination of a 2D operation-- so a cube face is valid, but
579// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400580// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500581bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400582{
583 switch (target)
584 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800585 case TextureTarget::_2D:
586 case TextureTarget::CubeMapNegativeX:
587 case TextureTarget::CubeMapNegativeY:
588 case TextureTarget::CubeMapNegativeZ:
589 case TextureTarget::CubeMapPositiveX:
590 case TextureTarget::CubeMapPositiveY:
591 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800592 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800593 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400594 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800595 default:
596 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500597 }
598}
599
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800600bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400601 PrimitiveMode transformFeedbackPrimitiveMode,
602 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800603{
604 ASSERT(context);
605
606 if (!context->getExtensions().geometryShader)
607 {
608 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
609 // that does not match the current transform feedback object's draw mode (if transform
610 // feedback is active), (3.0.2, section 2.14, pg 86)
611 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
612 }
613
614 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400615 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800616 {
Jamie Madill493f9572018-05-24 19:52:15 -0400617 case PrimitiveMode::Points:
618 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
619 case PrimitiveMode::Lines:
620 case PrimitiveMode::LineStrip:
621 case PrimitiveMode::LineLoop:
622 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
623 case PrimitiveMode::Triangles:
624 case PrimitiveMode::TriangleFan:
625 case PrimitiveMode::TriangleStrip:
626 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800627 default:
628 UNREACHABLE();
629 return false;
630 }
631}
632
Jamie Madill5b772312018-03-08 20:28:32 -0500633bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400634 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400635 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500636 DrawElementsType type,
Jamie Madillbe849e42017-05-02 15:49:00 -0400637 const GLvoid *indices,
638 GLsizei primcount)
639{
640 if (primcount < 0)
641 {
Jamie Madille0472f32018-11-27 16:32:45 -0500642 context->validationError(GL_INVALID_VALUE, kNegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400643 return false;
644 }
645
646 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
647 {
648 return false;
649 }
650
Jamie Madill9fdaa492018-02-16 10:52:11 -0500651 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400652}
653
654bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400655 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400656 GLint first,
657 GLsizei count,
658 GLsizei primcount)
659{
660 if (primcount < 0)
661 {
Jamie Madille0472f32018-11-27 16:32:45 -0500662 context->validationError(GL_INVALID_VALUE, kNegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400663 return false;
664 }
665
666 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
667 {
668 return false;
669 }
670
Jamie Madill9fdaa492018-02-16 10:52:11 -0500671 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400672}
673
Jamie Madill5b772312018-03-08 20:28:32 -0500674bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400675{
676 // Verify there is at least one active attribute with a divisor of zero
677 const State &state = context->getGLState();
678
Jamie Madill785e8a02018-10-04 17:42:00 -0400679 Program *program = state.getLinkedProgram(context);
Jamie Madillbe849e42017-05-02 15:49:00 -0400680
681 const auto &attribs = state.getVertexArray()->getVertexAttributes();
682 const auto &bindings = state.getVertexArray()->getVertexBindings();
683 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
684 {
685 const VertexAttribute &attrib = attribs[attributeIndex];
686 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300687 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400688 {
689 return true;
690 }
691 }
692
Jamie Madille0472f32018-11-27 16:32:45 -0500693 context->validationError(GL_INVALID_OPERATION, kNoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400694 return false;
695}
696
Jamie Madill5b772312018-03-08 20:28:32 -0500697bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500698{
699 switch (target)
700 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800701 case TextureType::_3D:
702 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800703 return true;
704 default:
705 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400706 }
707}
708
Jamie Madill5b772312018-03-08 20:28:32 -0500709bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800710{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800711 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800712 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800713 case TextureType::_2D:
714 case TextureType::_2DArray:
715 case TextureType::_2DMultisample:
716 case TextureType::CubeMap:
717 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800718 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800719 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400720 return context->getExtensions().textureRectangle;
Olli Etuahod310a432018-08-24 15:40:23 +0300721 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300722 return context->getExtensions().textureStorageMultisample2DArray;
He Yunchao11b038b2016-11-22 21:24:04 +0800723 default:
724 return false;
725 }
726}
727
Jamie Madill5b772312018-03-08 20:28:32 -0500728bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500729{
He Yunchaoced53ae2016-11-29 15:00:51 +0800730 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
731 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400732 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500733
734 switch (target)
735 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 case GL_FRAMEBUFFER:
737 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400738
He Yunchaoced53ae2016-11-29 15:00:51 +0800739 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800740 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400741 return (context->getExtensions().framebufferBlit ||
742 context->getClientMajorVersion() >= 3);
743
He Yunchaoced53ae2016-11-29 15:00:51 +0800744 default:
745 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500746 }
747}
748
Jamie Madill5b772312018-03-08 20:28:32 -0500749bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400750{
Jamie Madillc29968b2016-01-20 11:17:23 -0500751 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400752 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800753 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400754 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800755 case TextureType::_2D:
756 case TextureType::_2DArray:
757 case TextureType::_2DMultisample:
Olli Etuahod310a432018-08-24 15:40:23 +0300758 case TextureType::_2DMultisampleArray:
759 // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
760 // level-of-detail" for multisample textures should be. Could maybe make it zero.
Jamie Madillc29968b2016-01-20 11:17:23 -0500761 maxDimension = caps.max2DTextureSize;
762 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800763 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800764 maxDimension = caps.maxCubeMapTextureSize;
765 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800766 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400767 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800768 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800769 maxDimension = caps.max3DTextureSize;
770 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800771 default:
772 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400773 }
774
Jamie Madill43da7c42018-08-01 11:34:49 -0400775 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400776}
777
Jamie Madill5b772312018-03-08 20:28:32 -0500778bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800779 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700780 GLint level,
781 GLsizei width,
782 GLsizei height,
783 GLsizei depth,
784 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400785{
Brandon Jones6cad5662017-06-14 13:25:13 -0700786 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400787 {
Jamie Madille0472f32018-11-27 16:32:45 -0500788 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400789 return false;
790 }
Austin Kinross08528e12015-10-07 16:24:40 -0700791 // TexSubImage parameters can be NPOT without textureNPOT extension,
792 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500793 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500794 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500795 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400796 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400797 {
Jamie Madille0472f32018-11-27 16:32:45 -0500798 context->validationError(GL_INVALID_VALUE, kTextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400799 return false;
800 }
801
802 if (!ValidMipLevel(context, target, level))
803 {
Jamie Madille0472f32018-11-27 16:32:45 -0500804 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400805 return false;
806 }
807
808 return true;
809}
810
Geoff Lang966c9402017-04-18 12:38:27 -0400811bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
812{
813 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
814 (size % blockSize == 0);
815}
816
Jamie Madill5b772312018-03-08 20:28:32 -0500817bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500818 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400819 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500820 GLsizei width,
821 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400822{
Jamie Madill43da7c42018-08-01 11:34:49 -0400823 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400824 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400825 {
826 return false;
827 }
828
Geoff Lang966c9402017-04-18 12:38:27 -0400829 if (width < 0 || height < 0)
830 {
831 return false;
832 }
833
834 if (CompressedTextureFormatRequiresExactSize(internalFormat))
835 {
836 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
837 // block size for level 0 but WebGL disallows this.
838 bool smallerThanBlockSizeAllowed =
839 level > 0 || !context->getExtensions().webglCompatibility;
840
841 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
842 smallerThanBlockSizeAllowed) ||
843 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
844 smallerThanBlockSizeAllowed))
845 {
846 return false;
847 }
848 }
849
850 return true;
851}
852
Jamie Madill5b772312018-03-08 20:28:32 -0500853bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400854 GLenum internalFormat,
855 GLint xoffset,
856 GLint yoffset,
857 GLsizei width,
858 GLsizei height,
859 size_t textureWidth,
860 size_t textureHeight)
861{
Jamie Madill43da7c42018-08-01 11:34:49 -0400862 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400863 if (!formatInfo.compressed)
864 {
865 return false;
866 }
867
Geoff Lang44ff5a72017-02-03 15:15:43 -0500868 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400869 {
870 return false;
871 }
872
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500873 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400874 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500875 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400876 yoffset % formatInfo.compressedBlockHeight != 0)
877 {
878 return false;
879 }
880
881 // Allowed to either have data that is a multiple of block size or is smaller than the block
882 // size but fills the entire mip
883 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
884 static_cast<size_t>(width) == textureWidth &&
885 static_cast<size_t>(height) == textureHeight;
886 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
887 (height % formatInfo.compressedBlockHeight) == 0;
888 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400889 {
890 return false;
891 }
892 }
893
Geoff Langd4f180b2013-09-24 13:57:44 -0400894 return true;
895}
896
Jamie Madill5b772312018-03-08 20:28:32 -0500897bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800898 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400899 GLsizei width,
900 GLsizei height,
901 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400902 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400903 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400904 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400905 GLsizei imageSize)
906{
Jamie Madill43da7c42018-08-01 11:34:49 -0400907 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400908 if (pixelUnpackBuffer == nullptr && imageSize < 0)
909 {
910 // Checks are not required
911 return true;
912 }
913
914 // ...the data would be unpacked from the buffer object such that the memory reads required
915 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400916 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400917 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400918 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400919 const auto &unpack = context->getGLState().getUnpackState();
920
Jamie Madill7f232932018-09-12 11:03:06 -0400921 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
922 GLuint endByte = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400923 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400924 {
Jamie Madille0472f32018-11-27 16:32:45 -0500925 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400926 return false;
927 }
928
Geoff Langff5b2d52016-09-07 11:32:23 -0400929 if (pixelUnpackBuffer)
930 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400931 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400932 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
933 checkedEndByte += checkedOffset;
934
935 if (!checkedEndByte.IsValid() ||
936 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
937 {
938 // Overflow past the end of the buffer
Jamie Madille0472f32018-11-27 16:32:45 -0500939 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400940 return false;
941 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800942 if (context->getExtensions().webglCompatibility &&
943 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
944 {
Jamie Madill610640f2018-11-21 17:28:41 -0500945 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -0500946 kPixelUnpackBufferBoundForTransformFeedback);
James Darpiniane8a93c62018-01-04 18:02:24 -0800947 return false;
948 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400949 }
950 else
951 {
952 ASSERT(imageSize >= 0);
953 if (pixels == nullptr && imageSize != 0)
954 {
Jamie Madillc3e37312018-11-30 15:25:39 -0500955 context->validationError(GL_INVALID_OPERATION, kImageSizeMustBeZero);
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400956 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400957 }
958
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400959 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400960 {
Jamie Madillc3e37312018-11-30 15:25:39 -0500961 context->validationError(GL_INVALID_OPERATION, kImageSizeTooSmall);
Geoff Langff5b2d52016-09-07 11:32:23 -0400962 return false;
963 }
964 }
965
966 return true;
967}
968
Corentin Wallezad3ae902018-03-09 13:40:42 -0500969bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500970{
Geoff Lang37dde692014-01-31 16:34:54 -0500971 switch (queryType)
972 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500973 case QueryType::AnySamples:
974 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400975 return context->getClientMajorVersion() >= 3 ||
976 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500977 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800978 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500979 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800980 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500981 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500983 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800984 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 default:
986 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500987 }
988}
989
Jamie Madill5b772312018-03-08 20:28:32 -0500990bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400991 GLenum type,
992 GLboolean normalized,
993 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400994 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400995 bool pureInteger)
996{
997 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400998 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
999 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1000 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1001 // parameter exceeds 255.
1002 constexpr GLsizei kMaxWebGLStride = 255;
1003 if (stride > kMaxWebGLStride)
1004 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001005 context->validationError(GL_INVALID_VALUE, kStrideExceedsWebGLLimit);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001006 return false;
1007 }
1008
1009 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1010 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1011 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1012 // or an INVALID_OPERATION error is generated.
Frank Henigmand633b152018-10-04 23:34:31 -04001013 angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
1014 size_t typeSize = GetVertexFormatSize(internalType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001015
1016 ASSERT(isPow2(typeSize) && typeSize > 0);
1017 size_t sizeMask = (typeSize - 1);
1018 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1019 {
Jamie Madille0472f32018-11-27 16:32:45 -05001020 context->validationError(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001021 return false;
1022 }
1023
1024 if ((stride & sizeMask) != 0)
1025 {
Jamie Madille0472f32018-11-27 16:32:45 -05001026 context->validationError(GL_INVALID_OPERATION, kStrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001027 return false;
1028 }
1029
1030 return true;
1031}
1032
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001033Program *GetValidProgramNoResolve(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001034{
He Yunchaoced53ae2016-11-29 15:00:51 +08001035 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1036 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1037 // or program object and INVALID_OPERATION if the provided name identifies an object
1038 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001039
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001040 Program *validProgram = context->getProgramNoResolveLink(id);
Dian Xiang769769a2015-09-09 15:20:08 -07001041
1042 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001043 {
Dian Xiang769769a2015-09-09 15:20:08 -07001044 if (context->getShader(id))
1045 {
Jamie Madille0472f32018-11-27 16:32:45 -05001046 context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001047 }
1048 else
1049 {
Jamie Madille0472f32018-11-27 16:32:45 -05001050 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001051 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001052 }
Dian Xiang769769a2015-09-09 15:20:08 -07001053
1054 return validProgram;
1055}
1056
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001057Program *GetValidProgram(Context *context, GLuint id)
1058{
1059 Program *program = GetValidProgramNoResolve(context, id);
1060 if (program)
1061 {
Jamie Madill785e8a02018-10-04 17:42:00 -04001062 program->resolveLink(context);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001063 }
1064 return program;
1065}
1066
Jamie Madill5b772312018-03-08 20:28:32 -05001067Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001068{
1069 // See ValidProgram for spec details.
1070
1071 Shader *validShader = context->getShader(id);
1072
1073 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001074 {
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001075 if (context->getProgramNoResolveLink(id))
Dian Xiang769769a2015-09-09 15:20:08 -07001076 {
Jamie Madille0472f32018-11-27 16:32:45 -05001077 context->validationError(GL_INVALID_OPERATION, kExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001078 }
1079 else
1080 {
Jamie Madille0472f32018-11-27 16:32:45 -05001081 context->validationError(GL_INVALID_VALUE, kInvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001082 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001083 }
Dian Xiang769769a2015-09-09 15:20:08 -07001084
1085 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001086}
1087
Jamie Madill43da7c42018-08-01 11:34:49 -04001088bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001089{
Geoff Langfa125c92017-10-24 13:01:46 -04001090 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001091 {
Geoff Langfa125c92017-10-24 13:01:46 -04001092 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1093 {
Jamie Madille0472f32018-11-27 16:32:45 -05001094 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langfa125c92017-10-24 13:01:46 -04001095 return false;
1096 }
Jamie Madillb4472272014-07-03 10:38:55 -04001097
Geoff Langfa125c92017-10-24 13:01:46 -04001098 // Color attachment 0 is validated below because it is always valid
1099 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001100 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001101 {
Jamie Madille0472f32018-11-27 16:32:45 -05001102 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001103 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001104 }
1105 }
1106 else
1107 {
1108 switch (attachment)
1109 {
Geoff Langfa125c92017-10-24 13:01:46 -04001110 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 case GL_DEPTH_ATTACHMENT:
1112 case GL_STENCIL_ATTACHMENT:
1113 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001114
He Yunchaoced53ae2016-11-29 15:00:51 +08001115 case GL_DEPTH_STENCIL_ATTACHMENT:
1116 if (!context->getExtensions().webglCompatibility &&
1117 context->getClientMajorVersion() < 3)
1118 {
Jamie Madille0472f32018-11-27 16:32:45 -05001119 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
1121 }
1122 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001123
He Yunchaoced53ae2016-11-29 15:00:51 +08001124 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001125 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001126 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001127 }
1128 }
1129
1130 return true;
1131}
1132
Jamie Madill5b772312018-03-08 20:28:32 -05001133bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001134 GLenum target,
1135 GLsizei samples,
1136 GLenum internalformat,
1137 GLsizei width,
1138 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139{
1140 switch (target)
1141 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001142 case GL_RENDERBUFFER:
1143 break;
1144 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001145 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148
1149 if (width < 0 || height < 0 || samples < 0)
1150 {
Jamie Madille0472f32018-11-27 16:32:45 -05001151 context->validationError(GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001152 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001153 }
1154
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001155 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1156 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1157
1158 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001159 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001160 {
Jamie Madille0472f32018-11-27 16:32:45 -05001161 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001162 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001163 }
1164
1165 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1166 // 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 -08001167 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001168 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001169 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 {
Jamie Madille0472f32018-11-27 16:32:45 -05001171 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
Geoff Langaae65a42014-05-26 12:43:44 -04001175 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 {
Jamie Madille0472f32018-11-27 16:32:45 -05001177 context->validationError(GL_INVALID_VALUE, kResourceMaxRenderbufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04001178 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001179 }
1180
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001181 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 if (handle == 0)
1183 {
Jamie Madille0472f32018-11-27 16:32:45 -05001184 context->validationError(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001185 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001186 }
1187
1188 return true;
1189}
1190
Jamie Madill43da7c42018-08-01 11:34:49 -04001191bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001192 GLenum target,
1193 GLenum attachment,
1194 GLenum renderbuffertarget,
1195 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001196{
Geoff Lange8afa902017-09-27 15:00:43 -04001197 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001198 {
Jamie Madille0472f32018-11-27 16:32:45 -05001199 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001200 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001201 }
1202
Jamie Madill43da7c42018-08-01 11:34:49 -04001203 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001204
Jamie Madill84115c92015-04-23 15:00:07 -04001205 ASSERT(framebuffer);
1206 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207 {
Jamie Madille0472f32018-11-27 16:32:45 -05001208 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001209 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001210 }
1211
Jamie Madillb4472272014-07-03 10:38:55 -04001212 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001213 {
Jamie Madillb4472272014-07-03 10:38:55 -04001214 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001215 }
1216
Jamie Madillab9d82c2014-01-21 16:38:14 -05001217 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1218 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1219 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1220 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1221 if (renderbuffer != 0)
1222 {
1223 if (!context->getRenderbuffer(renderbuffer))
1224 {
Jamie Madille0472f32018-11-27 16:32:45 -05001225 context->validationError(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001226 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001227 }
1228 }
1229
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001230 return true;
1231}
1232
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001233bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001234 GLint srcX0,
1235 GLint srcY0,
1236 GLint srcX1,
1237 GLint srcY1,
1238 GLint dstX0,
1239 GLint dstY0,
1240 GLint dstX1,
1241 GLint dstY1,
1242 GLbitfield mask,
1243 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001244{
1245 switch (filter)
1246 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001247 case GL_NEAREST:
1248 break;
1249 case GL_LINEAR:
1250 break;
1251 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001252 context->validationError(GL_INVALID_ENUM, kBlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 }
1255
1256 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1257 {
Jamie Madille0472f32018-11-27 16:32:45 -05001258 context->validationError(GL_INVALID_VALUE, kBlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001259 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260 }
1261
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1263 // color buffer, leaving only nearest being unfiltered from above
1264 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1265 {
Jamie Madille0472f32018-11-27 16:32:45 -05001266 context->validationError(GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001267 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001268 }
1269
Jamie Madill7f232932018-09-12 11:03:06 -04001270 const auto &glState = context->getGLState();
1271 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1272 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001273
1274 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 {
Jamie Madille0472f32018-11-27 16:32:45 -05001276 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001277 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 }
1279
Jamie Madill427064d2018-04-13 16:20:34 -04001280 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001281 {
Jamie Madill48faf802014-11-06 15:27:22 -05001282 return false;
1283 }
1284
Jamie Madill427064d2018-04-13 16:20:34 -04001285 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001286 {
Jamie Madill48faf802014-11-06 15:27:22 -05001287 return false;
1288 }
1289
Qin Jiajiaaef92162018-02-27 13:51:44 +08001290 if (readFramebuffer->id() == drawFramebuffer->id())
1291 {
Jamie Madille0472f32018-11-27 16:32:45 -05001292 context->validationError(GL_INVALID_OPERATION, kBlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001293 return false;
1294 }
1295
Jamie Madille98b1b52018-03-08 09:47:23 -05001296 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297 {
Geoff Langb1196682014-07-23 13:47:29 -04001298 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 }
1300
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001301 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1302 // always run it in order to avoid triggering driver bugs.
1303 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1304 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001305 {
Jamie Madille0472f32018-11-27 16:32:45 -05001306 context->validationError(GL_INVALID_VALUE, kBlitDimensionsOutOfRange);
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001307 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001308 }
1309
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1311
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 if (mask & GL_COLOR_BUFFER_BIT)
1313 {
Jamie Madill7f232932018-09-12 11:03:06 -04001314 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1315 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001316
He Yunchao66a41a22016-12-15 16:45:05 +08001317 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001318 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001319 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320
Geoff Langa15472a2015-08-11 11:48:03 -04001321 for (size_t drawbufferIdx = 0;
1322 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 {
Geoff Langa15472a2015-08-11 11:48:03 -04001324 const FramebufferAttachment *attachment =
1325 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1326 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001328 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329
Geoff Langb2f3d052013-08-13 12:49:27 -04001330 // The GL ES 3.0.2 spec (pg 193) states that:
1331 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001332 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1333 // as well
1334 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1335 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001336 // Changes with EXT_color_buffer_float:
1337 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001338 GLenum readComponentType = readFormat.info->componentType;
1339 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001340 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001341 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001342 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001343 drawComponentType == GL_SIGNED_NORMALIZED);
1344
1345 if (extensions.colorBufferFloat)
1346 {
1347 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1348 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1349
1350 if (readFixedOrFloat != drawFixedOrFloat)
1351 {
Jamie Madill610640f2018-11-21 17:28:41 -05001352 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001353 kBlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001354 return false;
1355 }
1356 }
1357 else if (readFixedPoint != drawFixedPoint)
1358 {
Jamie Madille0472f32018-11-27 16:32:45 -05001359 context->validationError(GL_INVALID_OPERATION, kBlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001360 return false;
1361 }
1362
1363 if (readComponentType == GL_UNSIGNED_INT &&
1364 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 {
Jamie Madill610640f2018-11-21 17:28:41 -05001366 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001367 kBlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001368 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 }
1370
Jamie Madill6163c752015-12-07 16:32:59 -05001371 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 {
Jamie Madill610640f2018-11-21 17:28:41 -05001373 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001374 kBlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001375 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376 }
1377
Jamie Madilla3944d42016-07-22 22:13:26 -04001378 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001379 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 {
Jamie Madill610640f2018-11-21 17:28:41 -05001381 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001382 kBlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001383 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 }
Geoff Lange4915782017-04-12 15:19:07 -04001385
1386 if (context->getExtensions().webglCompatibility &&
1387 *readColorBuffer == *attachment)
1388 {
Jamie Madille0472f32018-11-27 16:32:45 -05001389 context->validationError(GL_INVALID_OPERATION, kBlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001390 return false;
1391 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 }
1393 }
1394
Jamie Madilla3944d42016-07-22 22:13:26 -04001395 if ((readFormat.info->componentType == GL_INT ||
1396 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1397 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 {
Jamie Madille0472f32018-11-27 16:32:45 -05001399 context->validationError(GL_INVALID_OPERATION, kBlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001400 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 }
He Yunchao66a41a22016-12-15 16:45:05 +08001403 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1404 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1405 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1406 // situation is an application error that would lead to a crash in ANGLE.
1407 else if (drawFramebuffer->hasEnabledDrawBuffer())
1408 {
Jamie Madille0472f32018-11-27 16:32:45 -05001409 context->validationError(GL_INVALID_OPERATION, kBlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001410 return false;
1411 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412 }
1413
He Yunchaoced53ae2016-11-29 15:00:51 +08001414 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001415 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1416 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001418 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001419 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001420 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001421 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001422 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001423 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001425 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 {
Kenneth Russell69382852017-07-21 16:38:44 -04001427 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428 {
Jamie Madill610640f2018-11-21 17:28:41 -05001429 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001430 kBlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001431 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001434 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 {
Jamie Madille0472f32018-11-27 16:32:45 -05001436 context->validationError(GL_INVALID_OPERATION, kBlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001437 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001438 }
Geoff Lange4915782017-04-12 15:19:07 -04001439
1440 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1441 {
Jamie Madille0472f32018-11-27 16:32:45 -05001442 context->validationError(GL_INVALID_OPERATION, kBlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001443 return false;
1444 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 }
He Yunchao66a41a22016-12-15 16:45:05 +08001446 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1447 else if (drawBuffer)
1448 {
Jamie Madille0472f32018-11-27 16:32:45 -05001449 context->validationError(GL_INVALID_OPERATION, kBlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001450 return false;
1451 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001452 }
1453 }
1454
Martin Radeva3ed4572017-07-27 18:29:37 +03001455 // ANGLE_multiview, Revision 1:
1456 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001457 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1458 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1459 // views in the current read framebuffer is more than one.
1460 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001461 {
Jamie Madille0472f32018-11-27 16:32:45 -05001462 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001463 return false;
1464 }
1465 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1466 {
Jamie Madille0472f32018-11-27 16:32:45 -05001467 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001468 return false;
1469 }
1470
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001471 return true;
1472}
1473
Jamie Madill4928b7c2017-06-20 12:57:39 -04001474bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001475 GLint x,
1476 GLint y,
1477 GLsizei width,
1478 GLsizei height,
1479 GLenum format,
1480 GLenum type,
1481 GLsizei bufSize,
1482 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001483 GLsizei *columns,
1484 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001485 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001486{
1487 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001488 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001489 return false;
1490 }
1491
Brandon Jonesd1049182018-03-28 10:02:20 -07001492 GLsizei writeLength = 0;
1493 GLsizei writeColumns = 0;
1494 GLsizei writeRows = 0;
1495
1496 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1497 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001498 {
Geoff Langb1196682014-07-23 13:47:29 -04001499 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001500 }
1501
Brandon Jonesd1049182018-03-28 10:02:20 -07001502 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001503 {
Geoff Langb1196682014-07-23 13:47:29 -04001504 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001505 }
1506
Brandon Jonesd1049182018-03-28 10:02:20 -07001507 SetRobustLengthParam(length, writeLength);
1508 SetRobustLengthParam(columns, writeColumns);
1509 SetRobustLengthParam(rows, writeRows);
1510
Jamie Madillc29968b2016-01-20 11:17:23 -05001511 return true;
1512}
1513
1514bool ValidateReadnPixelsEXT(Context *context,
1515 GLint x,
1516 GLint y,
1517 GLsizei width,
1518 GLsizei height,
1519 GLenum format,
1520 GLenum type,
1521 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001522 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001523{
1524 if (bufSize < 0)
1525 {
Jamie Madille0472f32018-11-27 16:32:45 -05001526 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001527 return false;
1528 }
1529
Geoff Lang62fce5b2016-09-30 10:46:35 -04001530 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001531 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001532}
Jamie Madill26e91952014-03-05 15:01:27 -05001533
Jamie Madill4928b7c2017-06-20 12:57:39 -04001534bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001535 GLint x,
1536 GLint y,
1537 GLsizei width,
1538 GLsizei height,
1539 GLenum format,
1540 GLenum type,
1541 GLsizei bufSize,
1542 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001543 GLsizei *columns,
1544 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001545 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001546{
Brandon Jonesd1049182018-03-28 10:02:20 -07001547 GLsizei writeLength = 0;
1548 GLsizei writeColumns = 0;
1549 GLsizei writeRows = 0;
1550
Geoff Lang62fce5b2016-09-30 10:46:35 -04001551 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001552 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001553 return false;
1554 }
1555
Brandon Jonesd1049182018-03-28 10:02:20 -07001556 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1557 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001558 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001559 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001560 }
1561
Brandon Jonesd1049182018-03-28 10:02:20 -07001562 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001563 {
1564 return false;
1565 }
1566
Brandon Jonesd1049182018-03-28 10:02:20 -07001567 SetRobustLengthParam(length, writeLength);
1568 SetRobustLengthParam(columns, writeColumns);
1569 SetRobustLengthParam(rows, writeRows);
1570
Geoff Lang62fce5b2016-09-30 10:46:35 -04001571 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001572}
1573
Jamie Madill43da7c42018-08-01 11:34:49 -04001574bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001575{
1576 if (!context->getExtensions().occlusionQueryBoolean &&
1577 !context->getExtensions().disjointTimerQuery)
1578 {
Jamie Madille0472f32018-11-27 16:32:45 -05001579 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001580 return false;
1581 }
1582
Olli Etuaho41997e72016-03-10 13:38:39 +02001583 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001584}
1585
Jamie Madill43da7c42018-08-01 11:34:49 -04001586bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001587{
1588 if (!context->getExtensions().occlusionQueryBoolean &&
1589 !context->getExtensions().disjointTimerQuery)
1590 {
Jamie Madille0472f32018-11-27 16:32:45 -05001591 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001592 return false;
1593 }
1594
Olli Etuaho41997e72016-03-10 13:38:39 +02001595 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001596}
1597
Jamie Madill43da7c42018-08-01 11:34:49 -04001598bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001599{
1600 if (!context->getExtensions().occlusionQueryBoolean &&
1601 !context->getExtensions().disjointTimerQuery)
1602 {
Jamie Madille0472f32018-11-27 16:32:45 -05001603 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Jamie Madillf0e04492017-08-26 15:28:42 -04001604 return false;
1605 }
1606
1607 return true;
1608}
1609
Jamie Madill43da7c42018-08-01 11:34:49 -04001610bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001611{
1612 if (!ValidQueryType(context, target))
1613 {
Jamie Madille0472f32018-11-27 16:32:45 -05001614 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001615 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001616 }
1617
1618 if (id == 0)
1619 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001620 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001621 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001622 }
1623
1624 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1625 // of zero, if the active query object name for <target> is non-zero (for the
1626 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1627 // the active query for either target is non-zero), if <id> is the name of an
1628 // existing query object whose type does not match <target>, or if <id> is the
1629 // active query object name for any query type, the error INVALID_OPERATION is
1630 // generated.
1631
1632 // Ensure no other queries are active
1633 // NOTE: If other queries than occlusion are supported, we will need to check
1634 // separately that:
1635 // a) The query ID passed is not the current active query for any target/type
1636 // b) There are no active queries for the requested target (and in the case
1637 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1638 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001639
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001640 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001641 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001642 context->validationError(GL_INVALID_OPERATION, kOtherQueryActive);
Geoff Langb1196682014-07-23 13:47:29 -04001643 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001644 }
1645
1646 Query *queryObject = context->getQuery(id, true, target);
1647
1648 // check that name was obtained with glGenQueries
1649 if (!queryObject)
1650 {
Jamie Madille0472f32018-11-27 16:32:45 -05001651 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001652 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001653 }
1654
1655 // check for type mismatch
1656 if (queryObject->getType() != target)
1657 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001658 context->validationError(GL_INVALID_OPERATION, kQueryTargetMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001659 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001660 }
1661
1662 return true;
1663}
1664
Jamie Madill43da7c42018-08-01 11:34:49 -04001665bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001666{
1667 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001668 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001669 {
Jamie Madille0472f32018-11-27 16:32:45 -05001670 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671 return false;
1672 }
1673
1674 return ValidateBeginQueryBase(context, target, id);
1675}
1676
Jamie Madill43da7c42018-08-01 11:34:49 -04001677bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001678{
1679 if (!ValidQueryType(context, target))
1680 {
Jamie Madille0472f32018-11-27 16:32:45 -05001681 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001682 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001683 }
1684
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001685 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001686
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001687 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001688 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001689 context->validationError(GL_INVALID_OPERATION, kQueryInactive);
Geoff Langb1196682014-07-23 13:47:29 -04001690 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001691 }
1692
Jamie Madill45c785d2014-05-13 14:09:34 -04001693 return true;
1694}
1695
Jamie Madill43da7c42018-08-01 11:34:49 -04001696bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697{
1698 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001699 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700 {
Jamie Madille0472f32018-11-27 16:32:45 -05001701 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702 return false;
1703 }
1704
1705 return ValidateEndQueryBase(context, target);
1706}
1707
Corentin Wallezad3ae902018-03-09 13:40:42 -05001708bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001709{
1710 if (!context->getExtensions().disjointTimerQuery)
1711 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001712 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713 return false;
1714 }
1715
Corentin Wallezad3ae902018-03-09 13:40:42 -05001716 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001717 {
Jamie Madille0472f32018-11-27 16:32:45 -05001718 context->validationError(GL_INVALID_ENUM, kInvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001719 return false;
1720 }
1721
1722 Query *queryObject = context->getQuery(id, true, target);
1723 if (queryObject == nullptr)
1724 {
Jamie Madille0472f32018-11-27 16:32:45 -05001725 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001726 return false;
1727 }
1728
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001729 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001730 {
Jamie Madille0472f32018-11-27 16:32:45 -05001731 context->validationError(GL_INVALID_OPERATION, kQueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 return false;
1733 }
1734
1735 return true;
1736}
1737
Corentin Wallezad3ae902018-03-09 13:40:42 -05001738bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001739{
Geoff Lang2186c382016-10-14 10:54:54 -04001740 if (numParams)
1741 {
1742 *numParams = 0;
1743 }
1744
Corentin Wallezad3ae902018-03-09 13:40:42 -05001745 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 {
Jamie Madille0472f32018-11-27 16:32:45 -05001747 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748 return false;
1749 }
1750
1751 switch (pname)
1752 {
1753 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001754 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001755 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001756 context->validationError(GL_INVALID_ENUM, kInvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001757 return false;
1758 }
1759 break;
1760 case GL_QUERY_COUNTER_BITS_EXT:
1761 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001762 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001763 {
Jamie Madille0472f32018-11-27 16:32:45 -05001764 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765 return false;
1766 }
1767 break;
1768 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001769 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770 return false;
1771 }
1772
Geoff Lang2186c382016-10-14 10:54:54 -04001773 if (numParams)
1774 {
1775 // All queries return only one value
1776 *numParams = 1;
1777 }
1778
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001779 return true;
1780}
1781
Corentin Wallezad3ae902018-03-09 13:40:42 -05001782bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001783{
1784 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001785 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001786 {
Jamie Madille0472f32018-11-27 16:32:45 -05001787 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 return false;
1789 }
1790
Geoff Lang2186c382016-10-14 10:54:54 -04001791 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001792}
1793
Geoff Lang2186c382016-10-14 10:54:54 -04001794bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001795 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001796 GLenum pname,
1797 GLsizei bufSize,
1798 GLsizei *length,
1799 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001800{
Geoff Lang2186c382016-10-14 10:54:54 -04001801 if (!ValidateRobustEntryPoint(context, bufSize))
1802 {
1803 return false;
1804 }
1805
Brandon Jonesd1049182018-03-28 10:02:20 -07001806 GLsizei numParams = 0;
1807
1808 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001809 {
1810 return false;
1811 }
1812
Brandon Jonesd1049182018-03-28 10:02:20 -07001813 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001814 {
1815 return false;
1816 }
1817
Brandon Jonesd1049182018-03-28 10:02:20 -07001818 SetRobustLengthParam(length, numParams);
1819
Geoff Lang2186c382016-10-14 10:54:54 -04001820 return true;
1821}
1822
1823bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1824{
1825 if (numParams)
1826 {
1827 *numParams = 0;
1828 }
1829
Corentin Wallezad3ae902018-03-09 13:40:42 -05001830 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001831
1832 if (!queryObject)
1833 {
Jamie Madille0472f32018-11-27 16:32:45 -05001834 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001835 return false;
1836 }
1837
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001838 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001839 {
Jamie Madille0472f32018-11-27 16:32:45 -05001840 context->validationError(GL_INVALID_OPERATION, kQueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841 return false;
1842 }
1843
1844 switch (pname)
1845 {
1846 case GL_QUERY_RESULT_EXT:
1847 case GL_QUERY_RESULT_AVAILABLE_EXT:
1848 break;
1849
1850 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001851 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001852 return false;
1853 }
1854
Geoff Lang2186c382016-10-14 10:54:54 -04001855 if (numParams)
1856 {
1857 *numParams = 1;
1858 }
1859
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001860 return true;
1861}
1862
1863bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1864{
1865 if (!context->getExtensions().disjointTimerQuery)
1866 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001867 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001868 return false;
1869 }
Geoff Lang2186c382016-10-14 10:54:54 -04001870 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1871}
1872
1873bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1874 GLuint id,
1875 GLenum pname,
1876 GLsizei bufSize,
1877 GLsizei *length,
1878 GLint *params)
1879{
1880 if (!context->getExtensions().disjointTimerQuery)
1881 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001882 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001883 return false;
1884 }
1885
1886 if (!ValidateRobustEntryPoint(context, bufSize))
1887 {
1888 return false;
1889 }
1890
Brandon Jonesd1049182018-03-28 10:02:20 -07001891 GLsizei numParams = 0;
1892
1893 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001894 {
1895 return false;
1896 }
1897
Brandon Jonesd1049182018-03-28 10:02:20 -07001898 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001899 {
1900 return false;
1901 }
1902
Brandon Jonesd1049182018-03-28 10:02:20 -07001903 SetRobustLengthParam(length, numParams);
1904
Geoff Lang2186c382016-10-14 10:54:54 -04001905 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001906}
1907
1908bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1909{
1910 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001911 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001912 {
Jamie Madille0472f32018-11-27 16:32:45 -05001913 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001914 return false;
1915 }
Geoff Lang2186c382016-10-14 10:54:54 -04001916 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1917}
1918
1919bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1920 GLuint id,
1921 GLenum pname,
1922 GLsizei bufSize,
1923 GLsizei *length,
1924 GLuint *params)
1925{
1926 if (!context->getExtensions().disjointTimerQuery &&
1927 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1928 {
Jamie Madille0472f32018-11-27 16:32:45 -05001929 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001930 return false;
1931 }
1932
1933 if (!ValidateRobustEntryPoint(context, bufSize))
1934 {
1935 return false;
1936 }
1937
Brandon Jonesd1049182018-03-28 10:02:20 -07001938 GLsizei numParams = 0;
1939
1940 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001941 {
1942 return false;
1943 }
1944
Brandon Jonesd1049182018-03-28 10:02:20 -07001945 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001946 {
1947 return false;
1948 }
1949
Brandon Jonesd1049182018-03-28 10:02:20 -07001950 SetRobustLengthParam(length, numParams);
1951
Geoff Lang2186c382016-10-14 10:54:54 -04001952 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001953}
1954
1955bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1956{
1957 if (!context->getExtensions().disjointTimerQuery)
1958 {
Jamie Madille0472f32018-11-27 16:32:45 -05001959 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001960 return false;
1961 }
Geoff Lang2186c382016-10-14 10:54:54 -04001962 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1963}
1964
1965bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1966 GLuint id,
1967 GLenum pname,
1968 GLsizei bufSize,
1969 GLsizei *length,
1970 GLint64 *params)
1971{
1972 if (!context->getExtensions().disjointTimerQuery)
1973 {
Jamie Madille0472f32018-11-27 16:32:45 -05001974 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001975 return false;
1976 }
1977
1978 if (!ValidateRobustEntryPoint(context, bufSize))
1979 {
1980 return false;
1981 }
1982
Brandon Jonesd1049182018-03-28 10:02:20 -07001983 GLsizei numParams = 0;
1984
1985 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001986 {
1987 return false;
1988 }
1989
Brandon Jonesd1049182018-03-28 10:02:20 -07001990 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001991 {
1992 return false;
1993 }
1994
Brandon Jonesd1049182018-03-28 10:02:20 -07001995 SetRobustLengthParam(length, numParams);
1996
Geoff Lang2186c382016-10-14 10:54:54 -04001997 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998}
1999
2000bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2001{
2002 if (!context->getExtensions().disjointTimerQuery)
2003 {
Jamie Madille0472f32018-11-27 16:32:45 -05002004 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002005 return false;
2006 }
Geoff Lang2186c382016-10-14 10:54:54 -04002007 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2008}
2009
2010bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2011 GLuint id,
2012 GLenum pname,
2013 GLsizei bufSize,
2014 GLsizei *length,
2015 GLuint64 *params)
2016{
2017 if (!context->getExtensions().disjointTimerQuery)
2018 {
Jamie Madille0472f32018-11-27 16:32:45 -05002019 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002020 return false;
2021 }
2022
2023 if (!ValidateRobustEntryPoint(context, bufSize))
2024 {
2025 return false;
2026 }
2027
Brandon Jonesd1049182018-03-28 10:02:20 -07002028 GLsizei numParams = 0;
2029
2030 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002031 {
2032 return false;
2033 }
2034
Brandon Jonesd1049182018-03-28 10:02:20 -07002035 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002036 {
2037 return false;
2038 }
2039
Brandon Jonesd1049182018-03-28 10:02:20 -07002040 SetRobustLengthParam(length, numParams);
2041
Geoff Lang2186c382016-10-14 10:54:54 -04002042 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002043}
2044
Jamie Madill5b772312018-03-08 20:28:32 -05002045bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002046 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002047 GLint location,
2048 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002049 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002050{
Jiajia Qin5451d532017-11-16 17:16:34 +08002051 // TODO(Jiajia): Add image uniform check in future.
2052 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002053 {
Jamie Madille0472f32018-11-27 16:32:45 -05002054 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002055 return false;
2056 }
2057
Jiajia Qin5451d532017-11-16 17:16:34 +08002058 if (!program)
2059 {
Jamie Madille0472f32018-11-27 16:32:45 -05002060 context->validationError(GL_INVALID_OPERATION, kInvalidProgramName);
Jiajia Qin5451d532017-11-16 17:16:34 +08002061 return false;
2062 }
2063
2064 if (!program->isLinked())
2065 {
Jamie Madille0472f32018-11-27 16:32:45 -05002066 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiajia Qin5451d532017-11-16 17:16:34 +08002067 return false;
2068 }
2069
2070 if (location == -1)
2071 {
2072 // Silently ignore the uniform command
2073 return false;
2074 }
2075
2076 const auto &uniformLocations = program->getUniformLocations();
2077 size_t castedLocation = static_cast<size_t>(location);
2078 if (castedLocation >= uniformLocations.size())
2079 {
Jamie Madille0472f32018-11-27 16:32:45 -05002080 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
Jiajia Qin5451d532017-11-16 17:16:34 +08002081 return false;
2082 }
2083
2084 const auto &uniformLocation = uniformLocations[castedLocation];
2085 if (uniformLocation.ignored)
2086 {
2087 // Silently ignore the uniform command
2088 return false;
2089 }
2090
2091 if (!uniformLocation.used())
2092 {
Jamie Madille0472f32018-11-27 16:32:45 -05002093 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
Jiajia Qin5451d532017-11-16 17:16:34 +08002094 return false;
2095 }
2096
2097 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2098
2099 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002100 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002101 {
Jamie Madille0472f32018-11-27 16:32:45 -05002102 context->validationError(GL_INVALID_OPERATION, kInvalidUniformCount);
Jiajia Qin5451d532017-11-16 17:16:34 +08002103 return false;
2104 }
2105
2106 *uniformOut = &uniform;
2107 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002108}
2109
Jamie Madill5b772312018-03-08 20:28:32 -05002110bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002111 GLenum uniformType,
2112 GLsizei count,
2113 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002114{
Jiajia Qin5451d532017-11-16 17:16:34 +08002115 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2116 // It is compatible with INT or BOOL.
2117 // Do these cheap tests first, for a little extra speed.
2118 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002119 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002120 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002121 }
2122
Jiajia Qin5451d532017-11-16 17:16:34 +08002123 if (IsSamplerType(uniformType))
2124 {
2125 // Check that the values are in range.
2126 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2127 for (GLsizei i = 0; i < count; ++i)
2128 {
2129 if (value[i] < 0 || value[i] >= max)
2130 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002131 context->validationError(GL_INVALID_VALUE, kSamplerUniformValueOutOfRange);
Jiajia Qin5451d532017-11-16 17:16:34 +08002132 return false;
2133 }
2134 }
2135 return true;
2136 }
2137
Jamie Madillc3e37312018-11-30 15:25:39 -05002138 context->validationError(GL_INVALID_OPERATION, kUniformTypeMismatch);
Jiajia Qin5451d532017-11-16 17:16:34 +08002139 return false;
2140}
2141
Jamie Madill5b772312018-03-08 20:28:32 -05002142bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002143{
2144 // Check that the value type is compatible with uniform type.
2145 if (valueType == uniformType)
2146 {
2147 return true;
2148 }
2149
Jamie Madillc3e37312018-11-30 15:25:39 -05002150 context->validationError(GL_INVALID_OPERATION, kUniformTypeMismatch);
Jiajia Qin5451d532017-11-16 17:16:34 +08002151 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002152}
2153
Jamie Madill5b772312018-03-08 20:28:32 -05002154bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002155{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002156 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002157 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002158 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2159 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002160}
2161
Jamie Madill5b772312018-03-08 20:28:32 -05002162bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002163{
2164 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002165 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmana98a6472017-02-02 21:38:32 -05002166 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2167 ValidateUniform1ivValue(context, uniform->type, count, value);
2168}
2169
Jamie Madill5b772312018-03-08 20:28:32 -05002170bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002171 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002172 GLint location,
2173 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002174 GLboolean transpose)
2175{
Geoff Lang92019432017-11-20 13:09:34 -05002176 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002177 {
Jamie Madille0472f32018-11-27 16:32:45 -05002178 context->validationError(GL_INVALID_VALUE, kES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04002179 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002180 }
2181
Jamie Madill62d31cb2015-09-11 13:25:51 -04002182 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002183 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002184 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2185 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002186}
2187
Jamie Madill5b772312018-03-08 20:28:32 -05002188bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002189{
2190 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2191 {
Jamie Madille0472f32018-11-27 16:32:45 -05002192 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Geoff Langb1196682014-07-23 13:47:29 -04002193 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002194 }
2195
Jamie Madill0af26e12015-03-05 19:54:33 -05002196 const Caps &caps = context->getCaps();
2197
Jamie Madill893ab082014-05-16 16:56:10 -04002198 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2199 {
2200 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2201
Jamie Madill0af26e12015-03-05 19:54:33 -05002202 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002203 {
Jamie Madille0472f32018-11-27 16:32:45 -05002204 context->validationError(GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer);
Geoff Langb1196682014-07-23 13:47:29 -04002205 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002206 }
2207 }
2208
2209 switch (pname)
2210 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002211 case GL_TEXTURE_BINDING_2D:
2212 case GL_TEXTURE_BINDING_CUBE_MAP:
2213 case GL_TEXTURE_BINDING_3D:
2214 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002215 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002216 break;
Olli Etuahod310a432018-08-24 15:40:23 +03002217 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
Olli Etuaho064458a2018-08-30 14:02:02 +03002218 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03002219 {
Jamie Madille0472f32018-11-27 16:32:45 -05002220 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
Olli Etuahod310a432018-08-24 15:40:23 +03002221 return false;
2222 }
2223 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002224 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2225 if (!context->getExtensions().textureRectangle)
2226 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002227 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002228 return false;
2229 }
2230 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002231 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2232 if (!context->getExtensions().eglStreamConsumerExternal &&
2233 !context->getExtensions().eglImageExternal)
2234 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002235 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08002236 return false;
2237 }
2238 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002239
He Yunchaoced53ae2016-11-29 15:00:51 +08002240 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2241 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002242 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002243 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2244 ASSERT(readFramebuffer);
2245
Jamie Madill610640f2018-11-21 17:28:41 -05002246 if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002247 {
Geoff Langb1196682014-07-23 13:47:29 -04002248 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002249 }
2250
Jamie Madille98b1b52018-03-08 09:47:23 -05002251 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002252 {
Jamie Madille0472f32018-11-27 16:32:45 -05002253 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002254 return false;
2255 }
2256
Jamie Madille98b1b52018-03-08 09:47:23 -05002257 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002258 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002259 {
Jamie Madille0472f32018-11-27 16:32:45 -05002260 context->validationError(GL_INVALID_OPERATION, kReadBufferNotAttached);
Geoff Langb1196682014-07-23 13:47:29 -04002261 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002262 }
2263 }
2264 break;
2265
He Yunchaoced53ae2016-11-29 15:00:51 +08002266 default:
2267 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002268 }
2269
2270 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002271 if (*numParams == 0)
2272 {
2273 return false;
2274 }
2275
2276 return true;
2277}
2278
Brandon Jonesd1049182018-03-28 10:02:20 -07002279bool ValidateGetBooleanvRobustANGLE(Context *context,
2280 GLenum pname,
2281 GLsizei bufSize,
2282 GLsizei *length,
2283 GLboolean *params)
2284{
2285 GLenum nativeType;
2286 unsigned int numParams = 0;
2287
2288 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2289 {
2290 return false;
2291 }
2292
2293 SetRobustLengthParam(length, numParams);
2294
2295 return true;
2296}
2297
2298bool ValidateGetFloatvRobustANGLE(Context *context,
2299 GLenum pname,
2300 GLsizei bufSize,
2301 GLsizei *length,
2302 GLfloat *params)
2303{
2304 GLenum nativeType;
2305 unsigned int numParams = 0;
2306
2307 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2308 {
2309 return false;
2310 }
2311
2312 SetRobustLengthParam(length, numParams);
2313
2314 return true;
2315}
2316
2317bool ValidateGetIntegervRobustANGLE(Context *context,
2318 GLenum pname,
2319 GLsizei bufSize,
2320 GLsizei *length,
2321 GLint *data)
2322{
2323 GLenum nativeType;
2324 unsigned int numParams = 0;
2325
2326 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2327 {
2328 return false;
2329 }
2330
2331 SetRobustLengthParam(length, numParams);
2332
2333 return true;
2334}
2335
2336bool ValidateGetInteger64vRobustANGLE(Context *context,
2337 GLenum pname,
2338 GLsizei bufSize,
2339 GLsizei *length,
2340 GLint64 *data)
2341{
2342 GLenum nativeType;
2343 unsigned int numParams = 0;
2344
2345 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2346 {
2347 return false;
2348 }
2349
2350 if (nativeType == GL_INT_64_ANGLEX)
2351 {
2352 CastStateValues(context, nativeType, pname, numParams, data);
2353 return false;
2354 }
2355
2356 SetRobustLengthParam(length, numParams);
2357 return true;
2358}
2359
Jamie Madill5b772312018-03-08 20:28:32 -05002360bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002361 GLenum pname,
2362 GLsizei bufSize,
2363 GLenum *nativeType,
2364 unsigned int *numParams)
2365{
2366 if (!ValidateRobustEntryPoint(context, bufSize))
2367 {
2368 return false;
2369 }
2370
2371 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2372 {
2373 return false;
2374 }
2375
2376 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002377 {
2378 return false;
2379 }
2380
2381 return true;
2382}
2383
Jamie Madill5b772312018-03-08 20:28:32 -05002384bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002385 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002386 GLint level,
2387 GLenum internalformat,
2388 bool isSubImage,
2389 GLint xoffset,
2390 GLint yoffset,
2391 GLint zoffset,
2392 GLint x,
2393 GLint y,
2394 GLsizei width,
2395 GLsizei height,
2396 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002397 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002398{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002399 TextureType texType = TextureTargetToType(target);
2400
Brandon Jones6cad5662017-06-14 13:25:13 -07002401 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002402 {
Jamie Madille0472f32018-11-27 16:32:45 -05002403 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07002404 return false;
2405 }
2406
2407 if (width < 0 || height < 0)
2408 {
Jamie Madille0472f32018-11-27 16:32:45 -05002409 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002410 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002411 }
2412
He Yunchaoced53ae2016-11-29 15:00:51 +08002413 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2414 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002415 {
Jamie Madille0472f32018-11-27 16:32:45 -05002416 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
Geoff Langb1196682014-07-23 13:47:29 -04002417 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002418 }
2419
2420 if (border != 0)
2421 {
Jamie Madille0472f32018-11-27 16:32:45 -05002422 context->validationError(GL_INVALID_VALUE, kInvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002423 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 }
2425
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002426 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002427 {
Jamie Madille0472f32018-11-27 16:32:45 -05002428 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002429 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002430 }
2431
Jamie Madill43da7c42018-08-01 11:34:49 -04002432 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002433 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002434 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002435 {
Geoff Langb1196682014-07-23 13:47:29 -04002436 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002437 }
2438
Jamie Madille98b1b52018-03-08 09:47:23 -05002439 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002440 {
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002442 }
2443
Martin Radev138064f2016-07-15 12:03:41 +03002444 if (readFramebuffer->getReadBufferState() == GL_NONE)
2445 {
Jamie Madille0472f32018-11-27 16:32:45 -05002446 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002447 return false;
2448 }
2449
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002450 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2451 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002452 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002453 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002454 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2455 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002456 {
Jamie Madille0472f32018-11-27 16:32:45 -05002457 context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002458 return false;
2459 }
2460
Martin Radev04e2c3b2017-07-27 16:54:35 +03002461 // ANGLE_multiview spec, Revision 1:
2462 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2463 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002464 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2465 // framebuffer is more than one.
2466 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002467 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002468 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
Martin Radev04e2c3b2017-07-27 16:54:35 +03002469 return false;
2470 }
2471
Jamie Madill43da7c42018-08-01 11:34:49 -04002472 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002473
Geoff Langaae65a42014-05-26 12:43:44 -04002474 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002475 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002476 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002477 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002478 maxDimension = caps.max2DTextureSize;
2479 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002480
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002481 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002482 maxDimension = caps.maxCubeMapTextureSize;
2483 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002484
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002485 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002486 maxDimension = caps.maxRectangleTextureSize;
2487 break;
2488
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002489 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002490 maxDimension = caps.max2DTextureSize;
2491 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002492
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002493 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002494 maxDimension = caps.max3DTextureSize;
2495 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002496
He Yunchaoced53ae2016-11-29 15:00:51 +08002497 default:
Jamie Madille0472f32018-11-27 16:32:45 -05002498 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08002499 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002500 }
2501
Jamie Madill43da7c42018-08-01 11:34:49 -04002502 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002503 if (!texture)
2504 {
Jamie Madille0472f32018-11-27 16:32:45 -05002505 context->validationError(GL_INVALID_OPERATION, kTextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002506 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002507 }
2508
Geoff Lang69cce582015-09-17 13:20:36 -04002509 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002510 {
Jamie Madille0472f32018-11-27 16:32:45 -05002511 context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
Geoff Langb1196682014-07-23 13:47:29 -04002512 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 }
2514
Jamie Madill43da7c42018-08-01 11:34:49 -04002515 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002516 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002517 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002518
Geoff Lang966c9402017-04-18 12:38:27 -04002519 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002520 {
Jamie Madille0472f32018-11-27 16:32:45 -05002521 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
Geoff Langa9be0dc2014-12-17 12:34:40 -05002522 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002523 }
2524
2525 if (isSubImage)
2526 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002527 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2528 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2529 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002530 {
Jamie Madille0472f32018-11-27 16:32:45 -05002531 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
Geoff Langb1196682014-07-23 13:47:29 -04002532 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002533 }
2534 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002535 else
2536 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002537 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002538 {
Jamie Madille0472f32018-11-27 16:32:45 -05002539 context->validationError(GL_INVALID_VALUE, kCubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002540 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002541 }
2542
Geoff Langeb66a6e2016-10-31 13:06:12 -04002543 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002544 {
Jamie Madille0472f32018-11-27 16:32:45 -05002545 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002546 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002547 }
2548
2549 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002550 if (static_cast<int>(width) > maxLevelDimension ||
2551 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002552 {
Jamie Madille0472f32018-11-27 16:32:45 -05002553 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002554 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002555 }
2556 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002557
Jamie Madill0c8abca2016-07-22 20:21:26 -04002558 if (textureFormatOut)
2559 {
2560 *textureFormatOut = texture->getFormat(target, level);
2561 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002562
2563 // Detect texture copying feedback loops for WebGL.
2564 if (context->getExtensions().webglCompatibility)
2565 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002566 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002567 {
Jamie Madille0472f32018-11-27 16:32:45 -05002568 context->validationError(GL_INVALID_OPERATION, kFeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002569 return false;
2570 }
2571 }
2572
Jamie Madill560a8d82014-05-21 13:06:20 -04002573 return true;
2574}
2575
Jamie Madillb42162f2018-08-20 12:58:37 -04002576// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2577// completeness check.
2578const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002579{
2580 const Extensions &extensions = context->getExtensions();
Jamie Madill7f232932018-09-12 11:03:06 -04002581 const State &state = context->getGLState();
Jamie Madille7d80f32018-08-08 15:49:23 -04002582
2583 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2584 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2585 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madilld84b6732018-09-06 15:54:35 -04002586 VertexArray *vertexArray = state.getVertexArray();
2587 ASSERT(vertexArray);
2588
2589 if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
Jamie Madille7d80f32018-08-08 15:49:23 -04002590 {
Jamie Madille0472f32018-11-27 16:32:45 -05002591 return kBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002592 }
2593
2594 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2595 // Section 6.10 of the WebGL 1.0 spec.
2596 Framebuffer *framebuffer = state.getDrawFramebuffer();
Jamie Madilld84b6732018-09-06 15:54:35 -04002597 ASSERT(framebuffer);
2598
Jamie Madille7d80f32018-08-08 15:49:23 -04002599 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2600 {
2601 ASSERT(framebuffer);
2602 const FramebufferAttachment *dsAttachment =
2603 framebuffer->getStencilOrDepthStencilAttachment();
2604 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2605 ASSERT(stencilBits <= 8);
2606
2607 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2608 if (depthStencilState.stencilTest && stencilBits > 0)
2609 {
2610 GLuint maxStencilValue = (1 << stencilBits) - 1;
2611
2612 bool differentRefs =
2613 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2614 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2615 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2616 (depthStencilState.stencilBackWritemask & maxStencilValue);
2617 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2618 (depthStencilState.stencilBackMask & maxStencilValue);
2619
2620 if (differentRefs || differentWritemasks || differentMasks)
2621 {
2622 if (!extensions.webglCompatibility)
2623 {
2624 WARN() << "This ANGLE implementation does not support separate front/back "
2625 "stencil writemasks, reference values, or stencil mask values.";
2626 }
Jamie Madille0472f32018-11-27 16:32:45 -05002627 return kStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002628 }
2629 }
2630 }
2631
2632 if (!framebuffer->isComplete(context))
2633 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002634 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
Jamie Madille0472f32018-11-27 16:32:45 -05002635 return kDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002636 }
2637
2638 if (context->getStateCache().hasAnyEnabledClientAttrib())
2639 {
2640 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2641 {
2642 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2643 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2644 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2645 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madille0472f32018-11-27 16:32:45 -05002646 return kVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002647 }
2648
2649 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2650 {
2651 // This is an application error that would normally result in a crash, but we catch it
2652 // and return an error
Jamie Madille0472f32018-11-27 16:32:45 -05002653 return kVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002654 }
2655 }
2656
2657 // If we are running GLES1, there is no current program.
2658 if (context->getClientVersion() >= Version(2, 0))
2659 {
Jamie Madill785e8a02018-10-04 17:42:00 -04002660 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002661 if (!program)
2662 {
Jamie Madille0472f32018-11-27 16:32:45 -05002663 return kProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002664 }
2665
2666 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2667 // vertex shader stage or fragment shader stage is a undefined behaviour.
2668 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2669 // produce undefined result.
2670 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2671 !program->hasLinkedShaderStage(ShaderType::Fragment))
2672 {
Jamie Madille0472f32018-11-27 16:32:45 -05002673 return kNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002674 }
2675
2676 if (!program->validateSamplers(nullptr, context->getCaps()))
2677 {
Jamie Madille0472f32018-11-27 16:32:45 -05002678 return kTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002679 }
2680
2681 if (extensions.multiview)
2682 {
2683 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2684 const int framebufferNumViews = framebuffer->getNumViews();
2685 if (framebufferNumViews != programNumViews)
2686 {
Jamie Madille0472f32018-11-27 16:32:45 -05002687 return kMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002688 }
2689
2690 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2691 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2692 framebufferNumViews > 1)
2693 {
Jamie Madille0472f32018-11-27 16:32:45 -05002694 return kMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002695 }
2696
2697 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2698 state.isQueryActive(QueryType::TimeElapsed))
2699 {
Jamie Madille0472f32018-11-27 16:32:45 -05002700 return kMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002701 }
2702 }
2703
2704 // Uniform buffer validation
2705 for (unsigned int uniformBlockIndex = 0;
2706 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2707 {
2708 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Jamie Madill7f232932018-09-12 11:03:06 -04002709 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Jamie Madille7d80f32018-08-08 15:49:23 -04002710 const OffsetBindingPointer<Buffer> &uniformBuffer =
2711 state.getIndexedUniformBuffer(blockBinding);
2712
2713 if (uniformBuffer.get() == nullptr)
2714 {
2715 // undefined behaviour
Jamie Madille0472f32018-11-27 16:32:45 -05002716 return kUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002717 }
2718
2719 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2720 if (uniformBufferSize < uniformBlock.dataSize)
2721 {
2722 // undefined behaviour
Jamie Madille0472f32018-11-27 16:32:45 -05002723 return kUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002724 }
2725
2726 if (extensions.webglCompatibility &&
2727 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2728 {
Jamie Madille0472f32018-11-27 16:32:45 -05002729 return kUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002730 }
2731 }
2732
2733 // Do some additonal WebGL-specific validation
2734 if (extensions.webglCompatibility)
2735 {
2736 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2737 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2738 transformFeedbackObject->buffersBoundForOtherUse())
2739 {
Jamie Madille0472f32018-11-27 16:32:45 -05002740 return kTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002741 }
2742
2743 // Detect rendering feedback loops for WebGL.
2744 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2745 {
Jamie Madille0472f32018-11-27 16:32:45 -05002746 return kFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002747 }
2748
2749 // Detect that the vertex shader input types match the attribute types
2750 if (!ValidateVertexShaderAttributeTypeMatch(context))
2751 {
Jamie Madille0472f32018-11-27 16:32:45 -05002752 return kVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002753 }
2754
2755 // Detect that the color buffer types match the fragment shader output types
2756 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2757 {
Jamie Madille0472f32018-11-27 16:32:45 -05002758 return kDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002759 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002760
2761 const VertexArray *vao = context->getGLState().getVertexArray();
2762 if (vao->hasTransformFeedbackBindingConflict(context))
2763 {
Jamie Madille0472f32018-11-27 16:32:45 -05002764 return kVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002765 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002766 }
2767 }
2768
Jamie Madillb42162f2018-08-20 12:58:37 -04002769 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002770}
2771
Jamie Madill16e28fd2018-09-12 11:03:05 -04002772bool ValidateDrawMode(Context *context, PrimitiveMode mode)
Jamie Madill250d33f2014-06-06 17:09:03 -04002773{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002774 const Extensions &extensions = context->getExtensions();
2775
Jamie Madill1aeb1312014-06-20 13:21:25 -04002776 switch (mode)
2777 {
Jamie Madill493f9572018-05-24 19:52:15 -04002778 case PrimitiveMode::Points:
2779 case PrimitiveMode::Lines:
2780 case PrimitiveMode::LineLoop:
2781 case PrimitiveMode::LineStrip:
2782 case PrimitiveMode::Triangles:
2783 case PrimitiveMode::TriangleStrip:
2784 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002785 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002786
Jamie Madill493f9572018-05-24 19:52:15 -04002787 case PrimitiveMode::LinesAdjacency:
2788 case PrimitiveMode::LineStripAdjacency:
2789 case PrimitiveMode::TrianglesAdjacency:
2790 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002791 if (!extensions.geometryShader)
2792 {
Jamie Madille0472f32018-11-27 16:32:45 -05002793 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shaofccebff2018-03-08 13:51:02 +08002794 return false;
2795 }
2796 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002797 default:
Jamie Madille0472f32018-11-27 16:32:45 -05002798 context->validationError(GL_INVALID_ENUM, kInvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002799 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002800 }
2801
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002802 // If we are running GLES1, there is no current program.
2803 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002804 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002805 const State &state = context->getGLState();
2806
Jamie Madill785e8a02018-10-04 17:42:00 -04002807 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002808 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002809
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002810 // Do geometry shader specific validations
2811 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002812 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002813 if (!IsCompatibleDrawModeWithGeometryShader(
2814 mode, program->getGeometryShaderInputPrimitiveType()))
2815 {
Jamie Madill610640f2018-11-21 17:28:41 -05002816 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05002817 kIncompatibleDrawModeAgainstGeometryShader);
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002818 return false;
2819 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002820 }
2821 }
2822
Jamie Madill9fdaa492018-02-16 10:52:11 -05002823 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002824}
2825
Jamie Madill5b772312018-03-08 20:28:32 -05002826bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002827 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002828 GLint first,
2829 GLsizei count,
2830 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002831{
Jamie Madillfd716582014-06-06 17:09:04 -04002832 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002833 {
Jamie Madille0472f32018-11-27 16:32:45 -05002834 context->validationError(GL_INVALID_VALUE, kNegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002835 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002836 }
2837
Jamie Madillf5c88e72018-12-08 09:56:38 -05002838 if (!ValidateDrawBase(context, mode, count))
Jamie Madill16e28fd2018-09-12 11:03:05 -04002839 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002840 return false;
2841 }
2842
Jamie Madill7f232932018-09-12 11:03:06 -04002843 const State &state = context->getGLState();
2844 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002845 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002846 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002847 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002848 if (!ValidateTransformFeedbackPrimitiveMode(context,
2849 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002850 {
Jamie Madille0472f32018-11-27 16:32:45 -05002851 context->validationError(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
James Darpinian30b604d2018-03-12 17:26:57 -07002852 return false;
2853 }
2854
2855 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2856 {
Jamie Madille0472f32018-11-27 16:32:45 -05002857 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackBufferTooSmall);
James Darpinian30b604d2018-03-12 17:26:57 -07002858 return false;
2859 }
Jamie Madillfd716582014-06-06 17:09:04 -04002860 }
2861
Corentin Wallez71168a02016-12-19 15:11:18 -08002862 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002863 // - first < 0 has been checked as an error condition.
2864 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002865 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002866 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002867 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002868 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002869 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2870 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2871 {
Jamie Madille0472f32018-11-27 16:32:45 -05002872 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madill9fdaa492018-02-16 10:52:11 -05002873 return false;
2874 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002875
Jamie Madill2da53562018-08-01 11:34:47 -04002876 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002877 {
2878 return false;
2879 }
Jamie Madillfd716582014-06-06 17:09:04 -04002880 }
2881
2882 return true;
2883}
2884
He Yunchaoced53ae2016-11-29 15:00:51 +08002885bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002886 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002887 GLint first,
2888 GLsizei count,
2889 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002890{
Geoff Lang63c5a592017-09-27 14:08:16 -04002891 if (!context->getExtensions().instancedArrays)
2892 {
Jamie Madille0472f32018-11-27 16:32:45 -05002893 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang63c5a592017-09-27 14:08:16 -04002894 return false;
2895 }
2896
Corentin Wallez170efbf2017-05-02 13:45:01 -04002897 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002898 {
2899 return false;
2900 }
2901
Corentin Wallez0dc97812017-06-22 14:38:44 -04002902 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002903}
2904
Jamie Madill8dc27f92018-11-29 11:45:44 -05002905bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, DrawElementsType type)
Jamie Madillfd716582014-06-06 17:09:04 -04002906{
Jamie Madill8dc27f92018-11-29 11:45:44 -05002907 if (!context->getStateCache().isValidDrawElementsType(type))
Jamie Madill250d33f2014-06-06 17:09:03 -04002908 {
Jamie Madill8dc27f92018-11-29 11:45:44 -05002909 if (type == DrawElementsType::UnsignedInt)
2910 {
Jamie Madille0472f32018-11-27 16:32:45 -05002911 context->validationError(GL_INVALID_ENUM, kTypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002912 return false;
Jamie Madill8dc27f92018-11-29 11:45:44 -05002913 }
2914
2915 ASSERT(type == DrawElementsType::InvalidEnum);
2916 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2917 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002918 }
2919
Jamie Madillf5c88e72018-12-08 09:56:38 -05002920 // TODO(jmadill): Cache all of these into fast checks. http://anglebug.com/2966
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002921 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002922
Jamie Madill43da7c42018-08-01 11:34:49 -04002923 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002924 if (curTransformFeedback && curTransformFeedback->isActive() &&
2925 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002926 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002927 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2928 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2929 if (context->getExtensions().geometryShader)
2930 {
2931 if (!ValidateTransformFeedbackPrimitiveMode(
2932 context, curTransformFeedback->getPrimitiveMode(), mode))
2933 {
Jamie Madille0472f32018-11-27 16:32:45 -05002934 context->validationError(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002935 return false;
2936 }
2937 }
2938 else
2939 {
2940 // It is an invalid operation to call DrawElements, DrawRangeElements or
2941 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2942 // 86)
Jamie Madill610640f2018-11-21 17:28:41 -05002943 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05002944 kUnsupportedDrawModeForTransformFeedback);
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002945 return false;
2946 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002947 }
2948
Jamie Madillf5c88e72018-12-08 09:56:38 -05002949 const VertexArray *vao = state.getVertexArray();
2950 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
2951
2952 if (elementArrayBuffer)
2953 {
2954 if (context->getExtensions().webglCompatibility)
2955 {
2956 if (elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
2957 {
2958 context->validationError(GL_INVALID_OPERATION,
2959 kElementArrayBufferBoundForTransformFeedback);
2960 return false;
2961 }
2962 }
2963 else if (elementArrayBuffer->isMapped())
2964 {
2965 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
2966 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the
2967 // WebGL 2.0 API. https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2968 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
2969 return false;
2970 }
2971 }
2972 else
2973 {
2974 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2975 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
2976 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
2977 if (!context->getGLState().areClientArraysEnabled() ||
2978 context->getExtensions().webglCompatibility)
2979 {
2980 context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
2981 return false;
2982 }
2983 }
2984
Jiajia Qind9671222016-11-29 16:30:31 +08002985 return true;
2986}
2987
Jamie Madill5b772312018-03-08 20:28:32 -05002988bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002989 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002990 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05002991 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04002992 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002993 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002994{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002995 if (!ValidateDrawElementsBase(context, mode, type))
Jamie Madillf5c88e72018-12-08 09:56:38 -05002996 {
Jiajia Qind9671222016-11-29 16:30:31 +08002997 return false;
Jamie Madillf5c88e72018-12-08 09:56:38 -05002998 }
Jiajia Qind9671222016-11-29 16:30:31 +08002999
Corentin Wallez170efbf2017-05-02 13:45:01 -04003000 if (!ValidateDrawBase(context, mode, count))
3001 {
3002 return false;
3003 }
3004
Jamie Madillf5c88e72018-12-08 09:56:38 -05003005 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04003006 const VertexArray *vao = state.getVertexArray();
Jamie Madillcd0a0a32018-10-18 18:41:57 -04003007 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003008
Jamie Madill8dc27f92018-11-29 11:45:44 -05003009 GLuint typeBytes = GetDrawElementsTypeSize(type);
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003010 ASSERT(isPow2(typeBytes) && typeBytes > 0);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003011
3012 if (context->getExtensions().webglCompatibility)
3013 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003014 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3015 {
3016 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3017 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3018 // data type passed to the call, or an INVALID_OPERATION error is generated.
Jamie Madille0472f32018-11-27 16:32:45 -05003019 context->validationError(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003020 return false;
3021 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003022
3023 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3024 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3025 // error is generated.
3026 if (reinterpret_cast<intptr_t>(indices) < 0)
3027 {
Jamie Madille0472f32018-11-27 16:32:45 -05003028 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003029 return false;
3030 }
Jamie Madillf5c88e72018-12-08 09:56:38 -05003031 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003032
Jamie Madillf5c88e72018-12-08 09:56:38 -05003033 // Early exit.
3034 if (count == 0)
3035 {
3036 return true;
3037 }
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003038
Jamie Madillf5c88e72018-12-08 09:56:38 -05003039 if (!elementArrayBuffer)
3040 {
3041 if (!indices)
James Darpiniane8a93c62018-01-04 18:02:24 -08003042 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003043 // This is an application error that would normally result in a crash, but we catch
3044 // it and return an error
3045 context->validationError(GL_INVALID_OPERATION, kElementArrayNoBufferOrPointer);
James Darpiniane8a93c62018-01-04 18:02:24 -08003046 return false;
3047 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003048 }
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003049 else
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003050 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003051 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3052 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3053 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3054 constexpr uint64_t kMaxTypeSize = 8;
3055 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3056 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3057 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3058
3059 uint64_t typeSize = typeBytes;
3060 uint64_t elementCount = static_cast<uint64_t>(count);
3061 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3062
3063 // Doing the multiplication here is overflow-safe
3064 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3065
3066 // The offset can be any value, check for overflows
3067 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3068 if (elementDataSizeNoOffset > kUint64Max - offset)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003069 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003070 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
3071 return false;
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003072 }
Jamie Madillf5c88e72018-12-08 09:56:38 -05003073
3074 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3075 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003076 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003077 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003078 return false;
3079 }
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003080 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003081
Jamie Madillf5c88e72018-12-08 09:56:38 -05003082 if (!context->getExtensions().robustBufferAccessBehavior && primcount > 0)
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003083 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003084 // Use the parameter buffer to retrieve and cache the index range.
3085 IndexRange indexRange;
3086 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
3087
3088 // If we use an index greater than our maximum supported index range, return an error.
3089 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
3090 // always return an error if possible here.
3091 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003092 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003093 context->validationError(GL_INVALID_OPERATION, kExceedsMaxElement);
3094 return false;
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003095 }
3096
Jamie Madillf5c88e72018-12-08 09:56:38 -05003097 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003098 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003099 return false;
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003100 }
Jamie Madillf5c88e72018-12-08 09:56:38 -05003101
3102 // No op if there are no real indices in the index data (all are primitive restart).
3103 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003104 }
3105
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003106 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003107}
3108
Jamie Madill5b772312018-03-08 20:28:32 -05003109bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003110 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003111 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05003112 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04003113 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003114 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003115{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003116 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003117}
3118
Geoff Lang3edfe032015-09-04 16:38:24 -04003119bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003120 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003121 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05003122 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04003123 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003124 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003125{
Geoff Lang63c5a592017-09-27 14:08:16 -04003126 if (!context->getExtensions().instancedArrays)
3127 {
Jamie Madille0472f32018-11-27 16:32:45 -05003128 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang63c5a592017-09-27 14:08:16 -04003129 return false;
3130 }
3131
Corentin Wallez170efbf2017-05-02 13:45:01 -04003132 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003133 {
3134 return false;
3135 }
3136
Corentin Wallez0dc97812017-06-22 14:38:44 -04003137 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003138}
3139
He Yunchaoced53ae2016-11-29 15:00:51 +08003140bool ValidateFramebufferTextureBase(Context *context,
3141 GLenum target,
3142 GLenum attachment,
3143 GLuint texture,
3144 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003145{
Geoff Lange8afa902017-09-27 15:00:43 -04003146 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003147 {
Jamie Madille0472f32018-11-27 16:32:45 -05003148 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003149 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003150 }
3151
3152 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003153 {
3154 return false;
3155 }
3156
Jamie Madill55ec3b12014-07-03 10:38:57 -04003157 if (texture != 0)
3158 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003159 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003160
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003161 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003162 {
Jamie Madille0472f32018-11-27 16:32:45 -05003163 context->validationError(GL_INVALID_OPERATION, kMissingTexture);
Geoff Langb1196682014-07-23 13:47:29 -04003164 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003165 }
3166
3167 if (level < 0)
3168 {
Jamie Madille0472f32018-11-27 16:32:45 -05003169 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04003170 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003171 }
3172 }
3173
Jamie Madill43da7c42018-08-01 11:34:49 -04003174 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003175 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003176
Jamie Madill84115c92015-04-23 15:00:07 -04003177 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003178 {
Jamie Madille0472f32018-11-27 16:32:45 -05003179 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003180 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003181 }
3182
3183 return true;
3184}
3185
Geoff Langb1196682014-07-23 13:47:29 -04003186bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003187{
3188 if (program == 0)
3189 {
Jamie Madille0472f32018-11-27 16:32:45 -05003190 context->validationError(GL_INVALID_VALUE, kProgramDoesNotExist);
Geoff Langb1196682014-07-23 13:47:29 -04003191 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003192 }
3193
Jamie Madill43da7c42018-08-01 11:34:49 -04003194 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003195 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003196 {
3197 return false;
3198 }
3199
Jamie Madill0063c512014-08-25 15:47:53 -04003200 if (!programObject || !programObject->isLinked())
3201 {
Jamie Madille0472f32018-11-27 16:32:45 -05003202 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003203 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003204 }
3205
Geoff Lang7dd2e102014-11-10 15:19:26 -05003206 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003207 {
Jamie Madille0472f32018-11-27 16:32:45 -05003208 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
Geoff Langb1196682014-07-23 13:47:29 -04003209 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003210 }
3211
Jamie Madill0063c512014-08-25 15:47:53 -04003212 return true;
3213}
3214
Geoff Langf41d0ee2016-10-07 13:04:23 -04003215static bool ValidateSizedGetUniform(Context *context,
3216 GLuint program,
3217 GLint location,
3218 GLsizei bufSize,
3219 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003220{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003221 if (length)
3222 {
3223 *length = 0;
3224 }
3225
Jamie Madill78f41802014-08-25 15:47:55 -04003226 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003227 {
Jamie Madill78f41802014-08-25 15:47:55 -04003228 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003229 }
3230
Geoff Langf41d0ee2016-10-07 13:04:23 -04003231 if (bufSize < 0)
3232 {
Jamie Madille0472f32018-11-27 16:32:45 -05003233 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003234 return false;
3235 }
3236
Jamie Madill44a6fbf2018-10-02 13:38:56 -04003237 Program *programObject = context->getProgramResolveLink(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003238 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003239
Jamie Madill78f41802014-08-25 15:47:55 -04003240 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003241 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003242 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003243 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003244 {
Jamie Madille0472f32018-11-27 16:32:45 -05003245 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003246 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003247 }
3248
Geoff Langf41d0ee2016-10-07 13:04:23 -04003249 if (length)
3250 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003251 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003252 }
3253
Jamie Madill0063c512014-08-25 15:47:53 -04003254 return true;
3255}
3256
He Yunchaoced53ae2016-11-29 15:00:51 +08003257bool ValidateGetnUniformfvEXT(Context *context,
3258 GLuint program,
3259 GLint location,
3260 GLsizei bufSize,
3261 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003262{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003263 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003264}
3265
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003266bool ValidateGetnUniformfvRobustANGLE(Context *context,
3267 GLuint program,
3268 GLint location,
3269 GLsizei bufSize,
3270 GLsizei *length,
3271 GLfloat *params)
3272{
3273 UNIMPLEMENTED();
3274 return false;
3275}
3276
He Yunchaoced53ae2016-11-29 15:00:51 +08003277bool ValidateGetnUniformivEXT(Context *context,
3278 GLuint program,
3279 GLint location,
3280 GLsizei bufSize,
3281 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003282{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003283 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3284}
3285
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003286bool ValidateGetnUniformivRobustANGLE(Context *context,
3287 GLuint program,
3288 GLint location,
3289 GLsizei bufSize,
3290 GLsizei *length,
3291 GLint *params)
3292{
3293 UNIMPLEMENTED();
3294 return false;
3295}
3296
3297bool ValidateGetnUniformuivRobustANGLE(Context *context,
3298 GLuint program,
3299 GLint location,
3300 GLsizei bufSize,
3301 GLsizei *length,
3302 GLuint *params)
3303{
3304 UNIMPLEMENTED();
3305 return false;
3306}
3307
Geoff Langf41d0ee2016-10-07 13:04:23 -04003308bool ValidateGetUniformfvRobustANGLE(Context *context,
3309 GLuint program,
3310 GLint location,
3311 GLsizei bufSize,
3312 GLsizei *length,
3313 GLfloat *params)
3314{
3315 if (!ValidateRobustEntryPoint(context, bufSize))
3316 {
3317 return false;
3318 }
3319
Brandon Jonesd1049182018-03-28 10:02:20 -07003320 GLsizei writeLength = 0;
3321
Geoff Langf41d0ee2016-10-07 13:04:23 -04003322 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003323 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3324 {
3325 return false;
3326 }
3327
3328 SetRobustLengthParam(length, writeLength);
3329
3330 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003331}
3332
3333bool ValidateGetUniformivRobustANGLE(Context *context,
3334 GLuint program,
3335 GLint location,
3336 GLsizei bufSize,
3337 GLsizei *length,
3338 GLint *params)
3339{
3340 if (!ValidateRobustEntryPoint(context, bufSize))
3341 {
3342 return false;
3343 }
3344
Brandon Jonesd1049182018-03-28 10:02:20 -07003345 GLsizei writeLength = 0;
3346
Geoff Langf41d0ee2016-10-07 13:04:23 -04003347 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003348 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3349 {
3350 return false;
3351 }
3352
3353 SetRobustLengthParam(length, writeLength);
3354
3355 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003356}
3357
3358bool ValidateGetUniformuivRobustANGLE(Context *context,
3359 GLuint program,
3360 GLint location,
3361 GLsizei bufSize,
3362 GLsizei *length,
3363 GLuint *params)
3364{
3365 if (!ValidateRobustEntryPoint(context, bufSize))
3366 {
3367 return false;
3368 }
3369
3370 if (context->getClientMajorVersion() < 3)
3371 {
Jamie Madille0472f32018-11-27 16:32:45 -05003372 context->validationError(GL_INVALID_OPERATION, kES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003373 return false;
3374 }
3375
Brandon Jonesd1049182018-03-28 10:02:20 -07003376 GLsizei writeLength = 0;
3377
Geoff Langf41d0ee2016-10-07 13:04:23 -04003378 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003379 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3380 {
3381 return false;
3382 }
3383
3384 SetRobustLengthParam(length, writeLength);
3385
3386 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003387}
3388
He Yunchaoced53ae2016-11-29 15:00:51 +08003389bool ValidateDiscardFramebufferBase(Context *context,
3390 GLenum target,
3391 GLsizei numAttachments,
3392 const GLenum *attachments,
3393 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003394{
3395 if (numAttachments < 0)
3396 {
Jamie Madille0472f32018-11-27 16:32:45 -05003397 context->validationError(GL_INVALID_VALUE, kNegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003398 return false;
3399 }
3400
3401 for (GLsizei i = 0; i < numAttachments; ++i)
3402 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003403 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003404 {
3405 if (defaultFramebuffer)
3406 {
Jamie Madille0472f32018-11-27 16:32:45 -05003407 context->validationError(GL_INVALID_ENUM, kDefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003408 return false;
3409 }
3410
3411 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3412 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003413 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003414 return false;
3415 }
3416 }
3417 else
3418 {
3419 switch (attachments[i])
3420 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003421 case GL_DEPTH_ATTACHMENT:
3422 case GL_STENCIL_ATTACHMENT:
3423 case GL_DEPTH_STENCIL_ATTACHMENT:
3424 if (defaultFramebuffer)
3425 {
Jamie Madill610640f2018-11-21 17:28:41 -05003426 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05003427 kDefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003428 return false;
3429 }
3430 break;
3431 case GL_COLOR:
3432 case GL_DEPTH:
3433 case GL_STENCIL:
3434 if (!defaultFramebuffer)
3435 {
Jamie Madill610640f2018-11-21 17:28:41 -05003436 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05003437 kDefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003438 return false;
3439 }
3440 break;
3441 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003442 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003443 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003444 }
3445 }
3446 }
3447
3448 return true;
3449}
3450
Austin Kinross6ee1e782015-05-29 17:05:37 -07003451bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3452{
Jamie Madill007530e2017-12-28 14:27:04 -05003453 if (!context->getExtensions().debugMarker)
3454 {
3455 // The debug marker calls should not set error state
3456 // However, it seems reasonable to set an error state if the extension is not enabled
Jamie Madille0472f32018-11-27 16:32:45 -05003457 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill007530e2017-12-28 14:27:04 -05003458 return false;
3459 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003460
Jamie Madill007530e2017-12-28 14:27:04 -05003461 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003462 if (length < 0)
3463 {
3464 return false;
3465 }
3466
3467 if (marker == nullptr)
3468 {
3469 return false;
3470 }
3471
3472 return true;
3473}
3474
3475bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3476{
Jamie Madill007530e2017-12-28 14:27:04 -05003477 if (!context->getExtensions().debugMarker)
3478 {
3479 // The debug marker calls should not set error state
3480 // However, it seems reasonable to set an error state if the extension is not enabled
Jamie Madille0472f32018-11-27 16:32:45 -05003481 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill007530e2017-12-28 14:27:04 -05003482 return false;
3483 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003484
Jamie Madill007530e2017-12-28 14:27:04 -05003485 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003486 if (length < 0)
3487 {
3488 return false;
3489 }
3490
3491 if (length > 0 && marker == nullptr)
3492 {
3493 return false;
3494 }
3495
3496 return true;
3497}
3498
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003499bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003500{
Geoff Langa8406172015-07-21 16:53:39 -04003501 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3502 {
Jamie Madille0472f32018-11-27 16:32:45 -05003503 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langa8406172015-07-21 16:53:39 -04003504 return false;
3505 }
3506
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003507 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003508 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003509 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003510 if (!context->getExtensions().eglImage)
3511 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003512 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb66a9092016-05-16 15:59:14 -04003513 }
3514 break;
3515
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003516 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003517 if (!context->getExtensions().eglImageExternal)
3518 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003519 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb66a9092016-05-16 15:59:14 -04003520 }
Geoff Langa8406172015-07-21 16:53:39 -04003521 break;
3522
3523 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003524 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003525 return false;
3526 }
3527
Rafael Cintron05a449a2018-06-20 18:08:04 -07003528 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003529
Jamie Madill61e16b42017-06-19 11:13:23 -04003530 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003531 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003532 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003533 context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
Geoff Langa8406172015-07-21 16:53:39 -04003534 return false;
3535 }
3536
Jamie Madill007530e2017-12-28 14:27:04 -05003537 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003538 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003539 context->validationError(GL_INVALID_OPERATION, kEGLImageCannotCreate2DMultisampled);
Geoff Langa8406172015-07-21 16:53:39 -04003540 return false;
3541 }
3542
Yuly Novikov2eb54072018-08-22 16:41:26 -04003543 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003544 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003545 context->validationError(GL_INVALID_OPERATION, kEGLImageTextureFormatNotSupported);
Geoff Langa8406172015-07-21 16:53:39 -04003546 return false;
3547 }
3548
Geoff Langdcab33b2015-07-21 13:03:16 -04003549 return true;
3550}
3551
3552bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003553 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003554 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003555{
Geoff Langa8406172015-07-21 16:53:39 -04003556 if (!context->getExtensions().eglImage)
3557 {
Jamie Madille0472f32018-11-27 16:32:45 -05003558 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langa8406172015-07-21 16:53:39 -04003559 return false;
3560 }
3561
3562 switch (target)
3563 {
3564 case GL_RENDERBUFFER:
3565 break;
3566
3567 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003568 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003569 return false;
3570 }
3571
Rafael Cintron05a449a2018-06-20 18:08:04 -07003572 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003573
Jamie Madill61e16b42017-06-19 11:13:23 -04003574 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003575 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003576 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003577 context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
Geoff Langa8406172015-07-21 16:53:39 -04003578 return false;
3579 }
3580
Yuly Novikov2eb54072018-08-22 16:41:26 -04003581 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003582 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003583 context->validationError(GL_INVALID_OPERATION, kEGLImageRenderbufferFormatNotSupported);
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);
Jamie Madille0472f32018-11-27 16:32:45 -05003596 context->validationError(GL_INVALID_OPERATION, kInvalidVertexArray);
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 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003619 context->validationError(GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
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
Jamie Madillc3e37312018-11-30 15:25:39 -05003626 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003627 return false;
3628 }
3629
Geoff Langc5629752015-12-07 16:29:04 -05003630 return true;
3631}
3632
3633bool ValidateGetProgramBinaryBase(Context *context,
3634 GLuint program,
3635 GLsizei bufSize,
3636 GLsizei *length,
3637 GLenum *binaryFormat,
3638 void *binary)
3639{
3640 Program *programObject = GetValidProgram(context, program);
3641 if (programObject == nullptr)
3642 {
3643 return false;
3644 }
3645
3646 if (!programObject->isLinked())
3647 {
Jamie Madille0472f32018-11-27 16:32:45 -05003648 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003649 return false;
3650 }
3651
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003652 if (context->getCaps().programBinaryFormats.empty())
3653 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003654 context->validationError(GL_INVALID_OPERATION, kNoProgramBinaryFormats);
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003655 return false;
3656 }
3657
Geoff Langc5629752015-12-07 16:29:04 -05003658 return true;
3659}
Jamie Madillc29968b2016-01-20 11:17:23 -05003660
Jamie Madill5b772312018-03-08 20:28:32 -05003661bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003662{
3663 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003664 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003665 {
Jamie Madille0472f32018-11-27 16:32:45 -05003666 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Brandon Jonesafa75152017-07-21 13:11:29 -07003667 return false;
3668 }
3669 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3670 {
Jamie Madille0472f32018-11-27 16:32:45 -05003671 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003672 return false;
3673 }
3674
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003675 ASSERT(context->getGLState().getDrawFramebuffer());
3676 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003677 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3678
3679 // This should come first before the check for the default frame buffer
3680 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3681 // rather than INVALID_OPERATION
3682 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3683 {
3684 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3685
3686 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003687 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3688 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003689 {
3690 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003691 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3692 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3693 // 3.1 is still a bit ambiguous about the error, but future specs are
3694 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madillc3e37312018-11-30 15:25:39 -05003695 context->validationError(GL_INVALID_ENUM, kInvalidDrawBuffer);
Olli Etuaho84c9f592016-03-09 14:37:25 +02003696 return false;
3697 }
3698 else if (bufs[colorAttachment] >= maxColorAttachment)
3699 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003700 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
Jamie Madillc29968b2016-01-20 11:17:23 -05003701 return false;
3702 }
3703 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3704 frameBufferId != 0)
3705 {
3706 // INVALID_OPERATION-GL is bound to buffer and ith argument
3707 // is not COLOR_ATTACHMENTi or NONE
Jamie Madillc3e37312018-11-30 15:25:39 -05003708 context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferValue);
Jamie Madillc29968b2016-01-20 11:17:23 -05003709 return false;
3710 }
3711 }
3712
3713 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3714 // and n is not 1 or bufs is bound to value other than BACK and NONE
3715 if (frameBufferId == 0)
3716 {
3717 if (n != 1)
3718 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003719 context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferCountForDefault);
Jamie Madillc29968b2016-01-20 11:17:23 -05003720 return false;
3721 }
3722
3723 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3724 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003725 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferInvalidDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003726 return false;
3727 }
3728 }
3729
3730 return true;
3731}
3732
Geoff Lang496c02d2016-10-20 11:38:11 -07003733bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003734 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003735 GLenum pname,
3736 GLsizei *length,
3737 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003738{
Geoff Lang496c02d2016-10-20 11:38:11 -07003739 if (length)
3740 {
3741 *length = 0;
3742 }
3743
Corentin Walleze4477002017-12-01 14:39:58 -05003744 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003745 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003746 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003747 return false;
3748 }
3749
Geoff Lang496c02d2016-10-20 11:38:11 -07003750 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003751 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003752 case GL_BUFFER_MAP_POINTER:
3753 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003754
Geoff Lang496c02d2016-10-20 11:38:11 -07003755 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003756 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003757 return false;
3758 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003759
3760 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3761 // target bound to zero generate an INVALID_OPERATION error."
3762 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003763 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003764 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003765 context->validationError(GL_INVALID_OPERATION, kBufferPointerNotAvailable);
Olli Etuaho4f667482016-03-30 15:56:35 +03003766 return false;
3767 }
3768
Geoff Lang496c02d2016-10-20 11:38:11 -07003769 if (length)
3770 {
3771 *length = 1;
3772 }
3773
Olli Etuaho4f667482016-03-30 15:56:35 +03003774 return true;
3775}
3776
Corentin Wallez336129f2017-10-17 15:55:40 -04003777bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003778{
Corentin Walleze4477002017-12-01 14:39:58 -05003779 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003780 {
Jamie Madille0472f32018-11-27 16:32:45 -05003781 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003782 return false;
3783 }
3784
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003785 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003786
3787 if (buffer == nullptr || !buffer->isMapped())
3788 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003789 context->validationError(GL_INVALID_OPERATION, kBufferNotMapped);
Olli Etuaho4f667482016-03-30 15:56:35 +03003790 return false;
3791 }
3792
3793 return true;
3794}
3795
3796bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003797 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003798 GLintptr offset,
3799 GLsizeiptr length,
3800 GLbitfield access)
3801{
Corentin Walleze4477002017-12-01 14:39:58 -05003802 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003803 {
Jamie Madille0472f32018-11-27 16:32:45 -05003804 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003805 return false;
3806 }
3807
Brandon Jones6cad5662017-06-14 13:25:13 -07003808 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003809 {
Jamie Madille0472f32018-11-27 16:32:45 -05003810 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07003811 return false;
3812 }
3813
3814 if (length < 0)
3815 {
Jamie Madille0472f32018-11-27 16:32:45 -05003816 context->validationError(GL_INVALID_VALUE, kNegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003817 return false;
3818 }
3819
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003820 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003821
3822 if (!buffer)
3823 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003824 context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
Olli Etuaho4f667482016-03-30 15:56:35 +03003825 return false;
3826 }
3827
3828 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003829 CheckedNumeric<size_t> checkedOffset(offset);
3830 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003831
Jamie Madille2e406c2016-06-02 13:04:10 -04003832 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003833 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003834 context->validationError(GL_INVALID_VALUE, kMapOutOfRange);
Olli Etuaho4f667482016-03-30 15:56:35 +03003835 return false;
3836 }
3837
3838 // Check for invalid bits in the mask
3839 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3840 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3841 GL_MAP_UNSYNCHRONIZED_BIT;
3842
3843 if (access & ~(allAccessBits))
3844 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003845 context->validationError(GL_INVALID_VALUE, kInvalidAccessBits);
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 return false;
3847 }
3848
3849 if (length == 0)
3850 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003851 context->validationError(GL_INVALID_OPERATION, kLengthZero);
Olli Etuaho4f667482016-03-30 15:56:35 +03003852 return false;
3853 }
3854
3855 if (buffer->isMapped())
3856 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003857 context->validationError(GL_INVALID_OPERATION, kBufferAlreadyMapped);
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 return false;
3859 }
3860
3861 // Check for invalid bit combinations
3862 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3863 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003864 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
Olli Etuaho4f667482016-03-30 15:56:35 +03003865 return false;
3866 }
3867
3868 GLbitfield writeOnlyBits =
3869 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3870
3871 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3872 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003873 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsRead);
Olli Etuaho4f667482016-03-30 15:56:35 +03003874 return false;
3875 }
3876
3877 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3878 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003879 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
Olli Etuaho4f667482016-03-30 15:56:35 +03003880 return false;
3881 }
Geoff Lang79f71042017-08-14 16:43:43 -04003882
3883 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003884}
3885
3886bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003887 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003888 GLintptr offset,
3889 GLsizeiptr length)
3890{
Brandon Jones6cad5662017-06-14 13:25:13 -07003891 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003892 {
Jamie Madille0472f32018-11-27 16:32:45 -05003893 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07003894 return false;
3895 }
3896
3897 if (length < 0)
3898 {
Jamie Madille0472f32018-11-27 16:32:45 -05003899 context->validationError(GL_INVALID_VALUE, kNegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 return false;
3901 }
3902
Corentin Walleze4477002017-12-01 14:39:58 -05003903 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003904 {
Jamie Madille0472f32018-11-27 16:32:45 -05003905 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003906 return false;
3907 }
3908
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003909 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003910
3911 if (buffer == nullptr)
3912 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003913 context->validationError(GL_INVALID_OPERATION, kInvalidFlushZero);
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 return false;
3915 }
3916
3917 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3918 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003919 context->validationError(GL_INVALID_OPERATION, kInvalidFlushTarget);
Olli Etuaho4f667482016-03-30 15:56:35 +03003920 return false;
3921 }
3922
3923 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003924 CheckedNumeric<size_t> checkedOffset(offset);
3925 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003926
Jamie Madille2e406c2016-06-02 13:04:10 -04003927 if (!checkedSize.IsValid() ||
3928 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003929 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003930 context->validationError(GL_INVALID_VALUE, kInvalidFlushOutOfRange);
Olli Etuaho4f667482016-03-30 15:56:35 +03003931 return false;
3932 }
3933
3934 return true;
3935}
3936
Olli Etuaho41997e72016-03-10 13:38:39 +02003937bool ValidateGenOrDelete(Context *context, GLint n)
3938{
3939 if (n < 0)
3940 {
Jamie Madille0472f32018-11-27 16:32:45 -05003941 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003942 return false;
3943 }
3944 return true;
3945}
3946
Jamie Madill5b772312018-03-08 20:28:32 -05003947bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003948{
3949 if (!context->getExtensions().robustClientMemory)
3950 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003951 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langff5b2d52016-09-07 11:32:23 -04003952 return false;
3953 }
3954
3955 if (bufSize < 0)
3956 {
Jamie Madille0472f32018-11-27 16:32:45 -05003957 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003958 return false;
3959 }
3960
3961 return true;
3962}
3963
Jamie Madill5b772312018-03-08 20:28:32 -05003964bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003965{
3966 if (bufSize < numParams)
3967 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003968 context->validationError(GL_INVALID_OPERATION, kInsufficientParams);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003969 return false;
3970 }
3971
3972 return true;
3973}
3974
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003975bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003976 GLenum target,
3977 GLenum attachment,
3978 GLenum pname,
3979 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003980{
Geoff Lange8afa902017-09-27 15:00:43 -04003981 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003982 {
Jamie Madille0472f32018-11-27 16:32:45 -05003983 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003984 return false;
3985 }
3986
3987 int clientVersion = context->getClientMajorVersion();
3988
3989 switch (pname)
3990 {
3991 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3992 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3993 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3994 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3995 break;
3996
Martin Radeve5285d22017-07-14 16:23:53 +03003997 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3998 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3999 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4000 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4001 if (clientVersion < 3 || !context->getExtensions().multiview)
4002 {
Jamie Madille0472f32018-11-27 16:32:45 -05004003 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Martin Radeve5285d22017-07-14 16:23:53 +03004004 return false;
4005 }
4006 break;
4007
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4009 if (clientVersion < 3 && !context->getExtensions().sRGB)
4010 {
Jamie Madille0472f32018-11-27 16:32:45 -05004011 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004012 return false;
4013 }
4014 break;
4015
4016 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4017 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4018 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4019 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4020 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4021 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4022 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4023 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4024 if (clientVersion < 3)
4025 {
Jamie Madille0472f32018-11-27 16:32:45 -05004026 context->validationError(GL_INVALID_ENUM, kES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004027 return false;
4028 }
4029 break;
4030
Jiawei Shaoa8802472018-05-28 11:17:47 +08004031 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4032 if (!context->getExtensions().geometryShader)
4033 {
Jamie Madille0472f32018-11-27 16:32:45 -05004034 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shaoa8802472018-05-28 11:17:47 +08004035 return false;
4036 }
4037 break;
4038
Geoff Langff5b2d52016-09-07 11:32:23 -04004039 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004040 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Geoff Langff5b2d52016-09-07 11:32:23 -04004041 return false;
4042 }
4043
4044 // Determine if the attachment is a valid enum
4045 switch (attachment)
4046 {
4047 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004048 case GL_DEPTH:
4049 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004050 if (clientVersion < 3)
4051 {
Jamie Madille0472f32018-11-27 16:32:45 -05004052 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004053 return false;
4054 }
4055 break;
4056
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004057 case GL_DEPTH_STENCIL_ATTACHMENT:
4058 if (clientVersion < 3 && !context->isWebGL1())
4059 {
Jamie Madille0472f32018-11-27 16:32:45 -05004060 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004061 return false;
4062 }
4063 break;
4064
Geoff Langfa125c92017-10-24 13:01:46 -04004065 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004066 case GL_DEPTH_ATTACHMENT:
4067 case GL_STENCIL_ATTACHMENT:
4068 break;
4069
4070 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004071 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4072 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004073 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4074 {
Jamie Madille0472f32018-11-27 16:32:45 -05004075 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004076 return false;
4077 }
4078 break;
4079 }
4080
4081 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4082 ASSERT(framebuffer);
4083
4084 if (framebuffer->id() == 0)
4085 {
4086 if (clientVersion < 3)
4087 {
Jamie Madille0472f32018-11-27 16:32:45 -05004088 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004089 return false;
4090 }
4091
4092 switch (attachment)
4093 {
4094 case GL_BACK:
4095 case GL_DEPTH:
4096 case GL_STENCIL:
4097 break;
4098
4099 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004100 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004101 return false;
4102 }
4103 }
4104 else
4105 {
4106 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4107 {
4108 // Valid attachment query
4109 }
4110 else
4111 {
4112 switch (attachment)
4113 {
4114 case GL_DEPTH_ATTACHMENT:
4115 case GL_STENCIL_ATTACHMENT:
4116 break;
4117
4118 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004119 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004120 {
Jamie Madille0472f32018-11-27 16:32:45 -05004121 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004122 return false;
4123 }
4124 break;
4125
4126 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004127 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004128 return false;
4129 }
4130 }
4131 }
4132
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004133 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004134 if (attachmentObject)
4135 {
4136 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4137 attachmentObject->type() == GL_TEXTURE ||
4138 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4139
4140 switch (pname)
4141 {
4142 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4143 if (attachmentObject->type() != GL_RENDERBUFFER &&
4144 attachmentObject->type() != GL_TEXTURE)
4145 {
Jamie Madille0472f32018-11-27 16:32:45 -05004146 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004147 return false;
4148 }
4149 break;
4150
4151 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4152 if (attachmentObject->type() != GL_TEXTURE)
4153 {
Jamie Madille0472f32018-11-27 16:32:45 -05004154 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004155 return false;
4156 }
4157 break;
4158
4159 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4160 if (attachmentObject->type() != GL_TEXTURE)
4161 {
Jamie Madille0472f32018-11-27 16:32:45 -05004162 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004163 return false;
4164 }
4165 break;
4166
4167 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4168 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4169 {
Jamie Madille0472f32018-11-27 16:32:45 -05004170 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004171 return false;
4172 }
4173 break;
4174
4175 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4176 if (attachmentObject->type() != GL_TEXTURE)
4177 {
Jamie Madille0472f32018-11-27 16:32:45 -05004178 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004179 return false;
4180 }
4181 break;
4182
4183 default:
4184 break;
4185 }
4186 }
4187 else
4188 {
4189 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4190 // is NONE, then querying any other pname will generate INVALID_ENUM.
4191
4192 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4193 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4194 // INVALID_OPERATION for all other pnames
4195
4196 switch (pname)
4197 {
4198 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4199 break;
4200
4201 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4202 if (clientVersion < 3)
4203 {
Jamie Madill610640f2018-11-21 17:28:41 -05004204 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05004205 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004206 return false;
4207 }
4208 break;
4209
4210 default:
4211 if (clientVersion < 3)
4212 {
Jamie Madill610640f2018-11-21 17:28:41 -05004213 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05004214 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004215 return false;
4216 }
4217 else
4218 {
Jamie Madill610640f2018-11-21 17:28:41 -05004219 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05004220 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004221 return false;
4222 }
4223 }
4224 }
4225
Martin Radeve5285d22017-07-14 16:23:53 +03004226 if (numParams)
4227 {
4228 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4229 {
4230 // Only when the viewport offsets are queried we can have a varying number of output
4231 // parameters.
4232 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4233 *numParams = numViews * 2;
4234 }
4235 else
4236 {
4237 // For all other queries we can have only one output parameter.
4238 *numParams = 1;
4239 }
4240 }
4241
Geoff Langff5b2d52016-09-07 11:32:23 -04004242 return true;
4243}
4244
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004245bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004246 GLenum target,
4247 GLenum attachment,
4248 GLenum pname,
4249 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004250 GLsizei *length,
4251 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004252{
4253 if (!ValidateRobustEntryPoint(context, bufSize))
4254 {
4255 return false;
4256 }
4257
Brandon Jonesd1049182018-03-28 10:02:20 -07004258 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004259 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004260 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004261 {
4262 return false;
4263 }
4264
Brandon Jonesd1049182018-03-28 10:02:20 -07004265 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004266 {
4267 return false;
4268 }
4269
Brandon Jonesd1049182018-03-28 10:02:20 -07004270 SetRobustLengthParam(length, numParams);
4271
Geoff Langff5b2d52016-09-07 11:32:23 -04004272 return true;
4273}
4274
Jamie Madill5b772312018-03-08 20:28:32 -05004275bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004276 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004277 GLenum pname,
4278 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004279 GLsizei *length,
4280 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004281{
4282 if (!ValidateRobustEntryPoint(context, bufSize))
4283 {
4284 return false;
4285 }
4286
Brandon Jonesd1049182018-03-28 10:02:20 -07004287 GLsizei numParams = 0;
4288
4289 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004290 {
4291 return false;
4292 }
4293
Brandon Jonesd1049182018-03-28 10:02:20 -07004294 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004295 {
4296 return false;
4297 }
4298
Brandon Jonesd1049182018-03-28 10:02:20 -07004299 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004300 return true;
4301}
4302
Jamie Madill5b772312018-03-08 20:28:32 -05004303bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004304 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004305 GLenum pname,
4306 GLsizei bufSize,
4307 GLsizei *length,
4308 GLint64 *params)
4309{
Brandon Jonesd1049182018-03-28 10:02:20 -07004310 GLsizei numParams = 0;
4311
Geoff Langebebe1c2016-10-14 12:01:31 -04004312 if (!ValidateRobustEntryPoint(context, bufSize))
4313 {
4314 return false;
4315 }
4316
Brandon Jonesd1049182018-03-28 10:02:20 -07004317 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004318 {
4319 return false;
4320 }
4321
Brandon Jonesd1049182018-03-28 10:02:20 -07004322 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004323 {
4324 return false;
4325 }
4326
Brandon Jonesd1049182018-03-28 10:02:20 -07004327 SetRobustLengthParam(length, numParams);
4328
Geoff Langff5b2d52016-09-07 11:32:23 -04004329 return true;
4330}
4331
Jamie Madill5b772312018-03-08 20:28:32 -05004332bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004333{
4334 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004335 if (numParams)
4336 {
4337 *numParams = 1;
4338 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004339
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004340 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
4341 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
4342 ? GetValidProgramNoResolve(context, program)
4343 : GetValidProgram(context, program);
Geoff Langff5b2d52016-09-07 11:32:23 -04004344 if (!programObject)
4345 {
4346 return false;
4347 }
4348
4349 switch (pname)
4350 {
4351 case GL_DELETE_STATUS:
4352 case GL_LINK_STATUS:
4353 case GL_VALIDATE_STATUS:
4354 case GL_INFO_LOG_LENGTH:
4355 case GL_ATTACHED_SHADERS:
4356 case GL_ACTIVE_ATTRIBUTES:
4357 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4358 case GL_ACTIVE_UNIFORMS:
4359 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4360 break;
4361
4362 case GL_PROGRAM_BINARY_LENGTH:
4363 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4364 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004365 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004366 return false;
4367 }
4368 break;
4369
4370 case GL_ACTIVE_UNIFORM_BLOCKS:
4371 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4372 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4373 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4374 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4375 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4376 if (context->getClientMajorVersion() < 3)
4377 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004378 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Geoff Langff5b2d52016-09-07 11:32:23 -04004379 return false;
4380 }
4381 break;
4382
Yunchao He61afff12017-03-14 15:34:03 +08004383 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004384 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004385 if (context->getClientVersion() < Version(3, 1))
4386 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004387 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Yunchao He61afff12017-03-14 15:34:03 +08004388 return false;
4389 }
4390 break;
4391
Jiawei Shao6ae51612018-02-23 14:03:25 +08004392 case GL_COMPUTE_WORK_GROUP_SIZE:
4393 if (context->getClientVersion() < Version(3, 1))
4394 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004395 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004396 return false;
4397 }
4398
4399 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4400 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4401 // program which has not been linked successfully, or which does not contain objects to
4402 // form a compute shader.
4403 if (!programObject->isLinked())
4404 {
Jamie Madille0472f32018-11-27 16:32:45 -05004405 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004406 return false;
4407 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004408 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004409 {
Jamie Madille0472f32018-11-27 16:32:45 -05004410 context->validationError(GL_INVALID_OPERATION, kNoActiveComputeShaderStage);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004411 return false;
4412 }
4413 break;
4414
Jiawei Shao447bfac2018-03-14 14:23:40 +08004415 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4416 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4417 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4418 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4419 if (!context->getExtensions().geometryShader)
4420 {
Jamie Madille0472f32018-11-27 16:32:45 -05004421 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004422 return false;
4423 }
4424
4425 // [EXT_geometry_shader] Chapter 7.12
4426 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4427 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4428 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4429 // successfully, or which does not contain objects to form a geometry shader.
4430 if (!programObject->isLinked())
4431 {
Jamie Madille0472f32018-11-27 16:32:45 -05004432 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004433 return false;
4434 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004435 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004436 {
Jamie Madille0472f32018-11-27 16:32:45 -05004437 context->validationError(GL_INVALID_OPERATION, kNoActiveGeometryShaderStage);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004438 return false;
4439 }
4440 break;
4441
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004442 case GL_COMPLETION_STATUS_KHR:
4443 if (!context->getExtensions().parallelShaderCompile)
4444 {
Jamie Madille0472f32018-11-27 16:32:45 -05004445 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004446 return false;
4447 }
4448 break;
4449
Geoff Langff5b2d52016-09-07 11:32:23 -04004450 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004451 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004452 return false;
4453 }
4454
4455 return true;
4456}
4457
4458bool ValidateGetProgramivRobustANGLE(Context *context,
4459 GLuint program,
4460 GLenum pname,
4461 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004462 GLsizei *length,
4463 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004464{
4465 if (!ValidateRobustEntryPoint(context, bufSize))
4466 {
4467 return false;
4468 }
4469
Brandon Jonesd1049182018-03-28 10:02:20 -07004470 GLsizei numParams = 0;
4471
4472 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004473 {
4474 return false;
4475 }
4476
Brandon Jonesd1049182018-03-28 10:02:20 -07004477 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004478 {
4479 return false;
4480 }
4481
Brandon Jonesd1049182018-03-28 10:02:20 -07004482 SetRobustLengthParam(length, numParams);
4483
Geoff Langff5b2d52016-09-07 11:32:23 -04004484 return true;
4485}
4486
Geoff Lang740d9022016-10-07 11:20:52 -04004487bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4488 GLenum target,
4489 GLenum pname,
4490 GLsizei bufSize,
4491 GLsizei *length,
4492 GLint *params)
4493{
4494 if (!ValidateRobustEntryPoint(context, bufSize))
4495 {
4496 return false;
4497 }
4498
Brandon Jonesd1049182018-03-28 10:02:20 -07004499 GLsizei numParams = 0;
4500
4501 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004502 {
4503 return false;
4504 }
4505
Brandon Jonesd1049182018-03-28 10:02:20 -07004506 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004507 {
4508 return false;
4509 }
4510
Brandon Jonesd1049182018-03-28 10:02:20 -07004511 SetRobustLengthParam(length, numParams);
4512
Geoff Lang740d9022016-10-07 11:20:52 -04004513 return true;
4514}
4515
Geoff Langd7d0ed32016-10-07 11:33:51 -04004516bool ValidateGetShaderivRobustANGLE(Context *context,
4517 GLuint shader,
4518 GLenum pname,
4519 GLsizei bufSize,
4520 GLsizei *length,
4521 GLint *params)
4522{
4523 if (!ValidateRobustEntryPoint(context, bufSize))
4524 {
4525 return false;
4526 }
4527
Brandon Jonesd1049182018-03-28 10:02:20 -07004528 GLsizei numParams = 0;
4529
4530 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004531 {
4532 return false;
4533 }
4534
Brandon Jonesd1049182018-03-28 10:02:20 -07004535 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004536 {
4537 return false;
4538 }
4539
Brandon Jonesd1049182018-03-28 10:02:20 -07004540 SetRobustLengthParam(length, numParams);
4541
Geoff Langd7d0ed32016-10-07 11:33:51 -04004542 return true;
4543}
4544
Geoff Langc1984ed2016-10-07 12:41:00 -04004545bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004546 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004547 GLenum pname,
4548 GLsizei bufSize,
4549 GLsizei *length,
4550 GLfloat *params)
4551{
4552 if (!ValidateRobustEntryPoint(context, bufSize))
4553 {
4554 return false;
4555 }
4556
Brandon Jonesd1049182018-03-28 10:02:20 -07004557 GLsizei numParams = 0;
4558
4559 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004560 {
4561 return false;
4562 }
4563
Brandon Jonesd1049182018-03-28 10:02:20 -07004564 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004565 {
4566 return false;
4567 }
4568
Brandon Jonesd1049182018-03-28 10:02:20 -07004569 SetRobustLengthParam(length, numParams);
4570
Geoff Langc1984ed2016-10-07 12:41:00 -04004571 return true;
4572}
4573
Geoff Langc1984ed2016-10-07 12:41:00 -04004574bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004575 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004576 GLenum pname,
4577 GLsizei bufSize,
4578 GLsizei *length,
4579 GLint *params)
4580{
Brandon Jonesd1049182018-03-28 10:02:20 -07004581
Geoff Langc1984ed2016-10-07 12:41:00 -04004582 if (!ValidateRobustEntryPoint(context, bufSize))
4583 {
4584 return false;
4585 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004586 GLsizei numParams = 0;
4587 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004588 {
4589 return false;
4590 }
4591
Brandon Jonesd1049182018-03-28 10:02:20 -07004592 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004593 {
4594 return false;
4595 }
4596
Brandon Jonesd1049182018-03-28 10:02:20 -07004597 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004598 return true;
4599}
4600
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004601bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4602 TextureType target,
4603 GLenum pname,
4604 GLsizei bufSize,
4605 GLsizei *length,
4606 GLint *params)
4607{
4608 UNIMPLEMENTED();
4609 return false;
4610}
4611
4612bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4613 TextureType target,
4614 GLenum pname,
4615 GLsizei bufSize,
4616 GLsizei *length,
4617 GLuint *params)
4618{
4619 UNIMPLEMENTED();
4620 return false;
4621}
4622
Geoff Langc1984ed2016-10-07 12:41:00 -04004623bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004624 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004625 GLenum pname,
4626 GLsizei bufSize,
4627 const GLfloat *params)
4628{
4629 if (!ValidateRobustEntryPoint(context, bufSize))
4630 {
4631 return false;
4632 }
4633
Till Rathmannb8543632018-10-02 19:46:14 +02004634 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004635}
4636
Geoff Langc1984ed2016-10-07 12:41:00 -04004637bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004638 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004639 GLenum pname,
4640 GLsizei bufSize,
4641 const GLint *params)
4642{
4643 if (!ValidateRobustEntryPoint(context, bufSize))
4644 {
4645 return false;
4646 }
4647
Till Rathmannb8543632018-10-02 19:46:14 +02004648 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004649}
4650
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004651bool ValidateTexParameterIivRobustANGLE(Context *context,
4652 TextureType target,
4653 GLenum pname,
4654 GLsizei bufSize,
4655 const GLint *params)
4656{
4657 UNIMPLEMENTED();
4658 return false;
4659}
4660
4661bool ValidateTexParameterIuivRobustANGLE(Context *context,
4662 TextureType target,
4663 GLenum pname,
4664 GLsizei bufSize,
4665 const GLuint *params)
4666{
4667 UNIMPLEMENTED();
4668 return false;
4669}
4670
Geoff Langc1984ed2016-10-07 12:41:00 -04004671bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4672 GLuint sampler,
4673 GLenum pname,
Jamie Madill778bf092018-11-14 09:54:36 -05004674 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004675 GLsizei *length,
4676 GLfloat *params)
4677{
4678 if (!ValidateRobustEntryPoint(context, bufSize))
4679 {
4680 return false;
4681 }
4682
Brandon Jonesd1049182018-03-28 10:02:20 -07004683 GLsizei numParams = 0;
4684
4685 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004686 {
4687 return false;
4688 }
4689
Brandon Jonesd1049182018-03-28 10:02:20 -07004690 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004691 {
4692 return false;
4693 }
4694
Brandon Jonesd1049182018-03-28 10:02:20 -07004695 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004696 return true;
4697}
4698
Geoff Langc1984ed2016-10-07 12:41:00 -04004699bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4700 GLuint sampler,
4701 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004702 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004703 GLsizei *length,
4704 GLint *params)
4705{
4706 if (!ValidateRobustEntryPoint(context, bufSize))
4707 {
4708 return false;
4709 }
4710
Brandon Jonesd1049182018-03-28 10:02:20 -07004711 GLsizei numParams = 0;
4712
4713 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004714 {
4715 return false;
4716 }
4717
Brandon Jonesd1049182018-03-28 10:02:20 -07004718 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004719 {
4720 return false;
4721 }
4722
Brandon Jonesd1049182018-03-28 10:02:20 -07004723 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004724 return true;
4725}
4726
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004727bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4728 GLuint sampler,
4729 GLenum pname,
4730 GLsizei bufSize,
4731 GLsizei *length,
4732 GLint *params)
4733{
4734 UNIMPLEMENTED();
4735 return false;
4736}
4737
4738bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4739 GLuint sampler,
4740 GLenum pname,
4741 GLsizei bufSize,
4742 GLsizei *length,
4743 GLuint *params)
4744{
4745 UNIMPLEMENTED();
4746 return false;
4747}
4748
Geoff Langc1984ed2016-10-07 12:41:00 -04004749bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4750 GLuint sampler,
4751 GLenum pname,
4752 GLsizei bufSize,
4753 const GLfloat *params)
4754{
4755 if (!ValidateRobustEntryPoint(context, bufSize))
4756 {
4757 return false;
4758 }
4759
Till Rathmannb8543632018-10-02 19:46:14 +02004760 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004761}
4762
Geoff Langc1984ed2016-10-07 12:41:00 -04004763bool ValidateSamplerParameterivRobustANGLE(Context *context,
4764 GLuint sampler,
4765 GLenum pname,
4766 GLsizei bufSize,
4767 const GLint *params)
4768{
4769 if (!ValidateRobustEntryPoint(context, bufSize))
4770 {
4771 return false;
4772 }
4773
Till Rathmannb8543632018-10-02 19:46:14 +02004774 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004775}
4776
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004777bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4778 GLuint sampler,
4779 GLenum pname,
4780 GLsizei bufSize,
4781 const GLint *param)
4782{
4783 UNIMPLEMENTED();
4784 return false;
4785}
4786
4787bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4788 GLuint sampler,
4789 GLenum pname,
4790 GLsizei bufSize,
4791 const GLuint *param)
4792{
4793 UNIMPLEMENTED();
4794 return false;
4795}
4796
Geoff Lang0b031062016-10-13 14:30:04 -04004797bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4798 GLuint index,
4799 GLenum pname,
4800 GLsizei bufSize,
4801 GLsizei *length,
4802 GLfloat *params)
4803{
4804 if (!ValidateRobustEntryPoint(context, bufSize))
4805 {
4806 return false;
4807 }
4808
Brandon Jonesd1049182018-03-28 10:02:20 -07004809 GLsizei writeLength = 0;
4810
4811 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004812 {
4813 return false;
4814 }
4815
Brandon Jonesd1049182018-03-28 10:02:20 -07004816 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004817 {
4818 return false;
4819 }
4820
Brandon Jonesd1049182018-03-28 10:02:20 -07004821 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004822 return true;
4823}
4824
Geoff Lang0b031062016-10-13 14:30:04 -04004825bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4826 GLuint index,
4827 GLenum pname,
4828 GLsizei bufSize,
4829 GLsizei *length,
4830 GLint *params)
4831{
4832 if (!ValidateRobustEntryPoint(context, bufSize))
4833 {
4834 return false;
4835 }
4836
Brandon Jonesd1049182018-03-28 10:02:20 -07004837 GLsizei writeLength = 0;
4838
4839 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004840 {
4841 return false;
4842 }
4843
Brandon Jonesd1049182018-03-28 10:02:20 -07004844 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004845 {
4846 return false;
4847 }
4848
Brandon Jonesd1049182018-03-28 10:02:20 -07004849 SetRobustLengthParam(length, writeLength);
4850
Geoff Lang0b031062016-10-13 14:30:04 -04004851 return true;
4852}
4853
Geoff Lang0b031062016-10-13 14:30:04 -04004854bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4855 GLuint index,
4856 GLenum pname,
4857 GLsizei bufSize,
4858 GLsizei *length,
4859 void **pointer)
4860{
4861 if (!ValidateRobustEntryPoint(context, bufSize))
4862 {
4863 return false;
4864 }
4865
Brandon Jonesd1049182018-03-28 10:02:20 -07004866 GLsizei writeLength = 0;
4867
4868 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004869 {
4870 return false;
4871 }
4872
Brandon Jonesd1049182018-03-28 10:02:20 -07004873 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004874 {
4875 return false;
4876 }
4877
Brandon Jonesd1049182018-03-28 10:02:20 -07004878 SetRobustLengthParam(length, writeLength);
4879
Geoff Lang0b031062016-10-13 14:30:04 -04004880 return true;
4881}
4882
Geoff Lang0b031062016-10-13 14:30:04 -04004883bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4884 GLuint index,
4885 GLenum pname,
4886 GLsizei bufSize,
4887 GLsizei *length,
4888 GLint *params)
4889{
4890 if (!ValidateRobustEntryPoint(context, bufSize))
4891 {
4892 return false;
4893 }
4894
Brandon Jonesd1049182018-03-28 10:02:20 -07004895 GLsizei writeLength = 0;
4896
4897 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004898 {
4899 return false;
4900 }
4901
Brandon Jonesd1049182018-03-28 10:02:20 -07004902 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004903 {
4904 return false;
4905 }
4906
Brandon Jonesd1049182018-03-28 10:02:20 -07004907 SetRobustLengthParam(length, writeLength);
4908
Geoff Lang0b031062016-10-13 14:30:04 -04004909 return true;
4910}
4911
Geoff Lang0b031062016-10-13 14:30:04 -04004912bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4913 GLuint index,
4914 GLenum pname,
4915 GLsizei bufSize,
4916 GLsizei *length,
4917 GLuint *params)
4918{
4919 if (!ValidateRobustEntryPoint(context, bufSize))
4920 {
4921 return false;
4922 }
4923
Brandon Jonesd1049182018-03-28 10:02:20 -07004924 GLsizei writeLength = 0;
4925
4926 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004927 {
4928 return false;
4929 }
4930
Brandon Jonesd1049182018-03-28 10:02:20 -07004931 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004932 {
4933 return false;
4934 }
4935
Brandon Jonesd1049182018-03-28 10:02:20 -07004936 SetRobustLengthParam(length, writeLength);
4937
Geoff Lang0b031062016-10-13 14:30:04 -04004938 return true;
4939}
4940
Geoff Lang6899b872016-10-14 11:30:13 -04004941bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4942 GLuint program,
4943 GLuint uniformBlockIndex,
4944 GLenum pname,
4945 GLsizei bufSize,
4946 GLsizei *length,
4947 GLint *params)
4948{
4949 if (!ValidateRobustEntryPoint(context, bufSize))
4950 {
4951 return false;
4952 }
4953
Brandon Jonesd1049182018-03-28 10:02:20 -07004954 GLsizei writeLength = 0;
4955
4956 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4957 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004958 {
4959 return false;
4960 }
4961
Brandon Jonesd1049182018-03-28 10:02:20 -07004962 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004963 {
4964 return false;
4965 }
4966
Brandon Jonesd1049182018-03-28 10:02:20 -07004967 SetRobustLengthParam(length, writeLength);
4968
Geoff Lang6899b872016-10-14 11:30:13 -04004969 return true;
4970}
4971
Brandon Jones416aaf92018-04-10 08:10:16 -07004972bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004973 GLenum target,
4974 GLenum internalformat,
4975 GLenum pname,
4976 GLsizei bufSize,
4977 GLsizei *length,
4978 GLint *params)
4979{
4980 if (!ValidateRobustEntryPoint(context, bufSize))
4981 {
4982 return false;
4983 }
4984
Brandon Jonesd1049182018-03-28 10:02:20 -07004985 GLsizei numParams = 0;
4986
4987 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4988 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07004989 {
4990 return false;
4991 }
4992
Brandon Jonesd1049182018-03-28 10:02:20 -07004993 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07004994 {
4995 return false;
4996 }
4997
Brandon Jonesd1049182018-03-28 10:02:20 -07004998 SetRobustLengthParam(length, numParams);
4999
Geoff Lang0a9661f2016-10-20 10:59:20 -07005000 return true;
5001}
5002
Jamie Madill5b772312018-03-08 20:28:32 -05005003bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005004 GLuint attribIndex,
5005 GLint size,
5006 GLenum type,
5007 GLboolean pureInteger)
5008{
5009 const Caps &caps = context->getCaps();
5010 if (attribIndex >= caps.maxVertexAttributes)
5011 {
Jamie Madille0472f32018-11-27 16:32:45 -05005012 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005013 return false;
5014 }
5015
5016 if (size < 1 || size > 4)
5017 {
Jamie Madille0472f32018-11-27 16:32:45 -05005018 context->validationError(GL_INVALID_VALUE, kInvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005019 return false;
Shao80957d92017-02-20 21:25:59 +08005020 }
5021
5022 switch (type)
5023 {
5024 case GL_BYTE:
5025 case GL_UNSIGNED_BYTE:
5026 case GL_SHORT:
5027 case GL_UNSIGNED_SHORT:
5028 break;
5029
5030 case GL_INT:
5031 case GL_UNSIGNED_INT:
5032 if (context->getClientMajorVersion() < 3)
5033 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005034 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005035 return false;
5036 }
5037 break;
5038
5039 case GL_FIXED:
5040 case GL_FLOAT:
5041 if (pureInteger)
5042 {
Jamie Madille0472f32018-11-27 16:32:45 -05005043 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005044 return false;
5045 }
5046 break;
5047
5048 case GL_HALF_FLOAT:
5049 if (context->getClientMajorVersion() < 3)
5050 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005051 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005052 return false;
5053 }
5054 if (pureInteger)
5055 {
Jamie Madille0472f32018-11-27 16:32:45 -05005056 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005057 return false;
5058 }
5059 break;
5060
5061 case GL_INT_2_10_10_10_REV:
5062 case GL_UNSIGNED_INT_2_10_10_10_REV:
5063 if (context->getClientMajorVersion() < 3)
5064 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005065 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005066 return false;
5067 }
5068 if (pureInteger)
5069 {
Jamie Madille0472f32018-11-27 16:32:45 -05005070 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005071 return false;
5072 }
5073 if (size != 4)
5074 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005075 context->validationError(GL_INVALID_OPERATION, kInvalidVertexAttribSize2101010);
Shao80957d92017-02-20 21:25:59 +08005076 return false;
5077 }
5078 break;
5079
5080 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005081 context->validationError(GL_INVALID_ENUM, kInvalidType);
Shao80957d92017-02-20 21:25:59 +08005082 return false;
5083 }
5084
5085 return true;
5086}
5087
Geoff Lang76e65652017-03-27 14:58:02 -04005088// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5089// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5090// specified clear value and the type of a buffer that is being cleared generates an
5091// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005092bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005093 GLint drawbuffer,
5094 const GLenum *validComponentTypes,
5095 size_t validComponentTypeCount)
5096{
5097 const FramebufferAttachment *attachment =
5098 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5099 if (attachment)
5100 {
5101 GLenum componentType = attachment->getFormat().info->componentType;
5102 const GLenum *end = validComponentTypes + validComponentTypeCount;
5103 if (std::find(validComponentTypes, end, componentType) == end)
5104 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005105 context->validationError(GL_INVALID_OPERATION, kNoDefinedClearConversion);
Geoff Lang76e65652017-03-27 14:58:02 -04005106 return false;
5107 }
5108 }
5109
5110 return true;
5111}
5112
Jamie Madill5b772312018-03-08 20:28:32 -05005113bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005114{
5115 if (!ValidateRobustEntryPoint(context, dataSize))
5116 {
5117 return false;
5118 }
5119
Jamie Madill43da7c42018-08-01 11:34:49 -04005120 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005121 if (pixelUnpackBuffer == nullptr)
5122 {
5123 if (dataSize < imageSize)
5124 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005125 context->validationError(GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
Corentin Wallezb2931602017-04-11 15:58:57 -04005126 }
5127 }
5128 return true;
5129}
5130
Jamie Madill5b772312018-03-08 20:28:32 -05005131bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005132 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005133 GLenum pname,
5134 bool pointerVersion,
5135 GLsizei *numParams)
5136{
5137 if (numParams)
5138 {
5139 *numParams = 0;
5140 }
5141
Corentin Walleze4477002017-12-01 14:39:58 -05005142 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005143 {
Jamie Madille0472f32018-11-27 16:32:45 -05005144 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005145 return false;
5146 }
5147
5148 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5149 if (!buffer)
5150 {
5151 // A null buffer means that "0" is bound to the requested buffer target
Jamie Madille0472f32018-11-27 16:32:45 -05005152 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005153 return false;
5154 }
5155
5156 const Extensions &extensions = context->getExtensions();
5157
5158 switch (pname)
5159 {
5160 case GL_BUFFER_USAGE:
5161 case GL_BUFFER_SIZE:
5162 break;
5163
5164 case GL_BUFFER_ACCESS_OES:
5165 if (!extensions.mapBuffer)
5166 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005167 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005168 return false;
5169 }
5170 break;
5171
5172 case GL_BUFFER_MAPPED:
5173 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5174 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5175 !extensions.mapBufferRange)
5176 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005177 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005178 return false;
5179 }
5180 break;
5181
5182 case GL_BUFFER_MAP_POINTER:
5183 if (!pointerVersion)
5184 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005185 context->validationError(GL_INVALID_ENUM, kInvalidMapPointerQuery);
Jamie Madillbe849e42017-05-02 15:49:00 -04005186 return false;
5187 }
5188 break;
5189
5190 case GL_BUFFER_ACCESS_FLAGS:
5191 case GL_BUFFER_MAP_OFFSET:
5192 case GL_BUFFER_MAP_LENGTH:
5193 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5194 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005195 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005196 return false;
5197 }
5198 break;
5199
Geoff Lang79b91402018-10-04 15:11:30 -04005200 case GL_MEMORY_SIZE_ANGLE:
5201 if (!context->getExtensions().memorySize)
5202 {
Jamie Madille0472f32018-11-27 16:32:45 -05005203 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Geoff Lang79b91402018-10-04 15:11:30 -04005204 return false;
5205 }
5206 break;
5207
Jamie Madillbe849e42017-05-02 15:49:00 -04005208 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005209 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005210 return false;
5211 }
5212
5213 // All buffer parameter queries return one value.
5214 if (numParams)
5215 {
5216 *numParams = 1;
5217 }
5218
5219 return true;
5220}
5221
5222bool ValidateGetRenderbufferParameterivBase(Context *context,
5223 GLenum target,
5224 GLenum pname,
5225 GLsizei *length)
5226{
5227 if (length)
5228 {
5229 *length = 0;
5230 }
5231
5232 if (target != GL_RENDERBUFFER)
5233 {
Jamie Madille0472f32018-11-27 16:32:45 -05005234 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005235 return false;
5236 }
5237
5238 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5239 if (renderbuffer == nullptr)
5240 {
Jamie Madille0472f32018-11-27 16:32:45 -05005241 context->validationError(GL_INVALID_OPERATION, kRenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005242 return false;
5243 }
5244
5245 switch (pname)
5246 {
5247 case GL_RENDERBUFFER_WIDTH:
5248 case GL_RENDERBUFFER_HEIGHT:
5249 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5250 case GL_RENDERBUFFER_RED_SIZE:
5251 case GL_RENDERBUFFER_GREEN_SIZE:
5252 case GL_RENDERBUFFER_BLUE_SIZE:
5253 case GL_RENDERBUFFER_ALPHA_SIZE:
5254 case GL_RENDERBUFFER_DEPTH_SIZE:
5255 case GL_RENDERBUFFER_STENCIL_SIZE:
5256 break;
5257
5258 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5259 if (!context->getExtensions().framebufferMultisample)
5260 {
Jamie Madille0472f32018-11-27 16:32:45 -05005261 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005262 return false;
5263 }
5264 break;
5265
Geoff Lang79b91402018-10-04 15:11:30 -04005266 case GL_MEMORY_SIZE_ANGLE:
5267 if (!context->getExtensions().memorySize)
5268 {
Jamie Madille0472f32018-11-27 16:32:45 -05005269 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Geoff Lang79b91402018-10-04 15:11:30 -04005270 return false;
5271 }
5272 break;
5273
Jamie Madillbe849e42017-05-02 15:49:00 -04005274 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005275 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005276 return false;
5277 }
5278
5279 if (length)
5280 {
5281 *length = 1;
5282 }
5283 return true;
5284}
5285
5286bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5287{
5288 if (length)
5289 {
5290 *length = 0;
5291 }
5292
5293 if (GetValidShader(context, shader) == nullptr)
5294 {
5295 return false;
5296 }
5297
5298 switch (pname)
5299 {
5300 case GL_SHADER_TYPE:
5301 case GL_DELETE_STATUS:
5302 case GL_COMPILE_STATUS:
5303 case GL_INFO_LOG_LENGTH:
5304 case GL_SHADER_SOURCE_LENGTH:
5305 break;
5306
5307 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5308 if (!context->getExtensions().translatedShaderSource)
5309 {
Jamie Madille0472f32018-11-27 16:32:45 -05005310 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005311 return false;
5312 }
5313 break;
5314
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005315 case GL_COMPLETION_STATUS_KHR:
5316 if (!context->getExtensions().parallelShaderCompile)
5317 {
Jamie Madille0472f32018-11-27 16:32:45 -05005318 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005319 return false;
5320 }
5321 break;
5322
Jamie Madillbe849e42017-05-02 15:49:00 -04005323 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005324 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 return false;
5326 }
5327
5328 if (length)
5329 {
5330 *length = 1;
5331 }
5332 return true;
5333}
5334
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005335bool ValidateGetTexParameterBase(Context *context,
5336 TextureType target,
5337 GLenum pname,
5338 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005339{
5340 if (length)
5341 {
5342 *length = 0;
5343 }
5344
5345 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5346 {
Jamie Madille0472f32018-11-27 16:32:45 -05005347 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005348 return false;
5349 }
5350
5351 if (context->getTargetTexture(target) == nullptr)
5352 {
5353 // Should only be possible for external textures
Jamie Madille0472f32018-11-27 16:32:45 -05005354 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005355 return false;
5356 }
5357
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005358 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5359 {
Jamie Madille0472f32018-11-27 16:32:45 -05005360 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005361 return false;
5362 }
5363
Jamie Madillbe849e42017-05-02 15:49:00 -04005364 switch (pname)
5365 {
5366 case GL_TEXTURE_MAG_FILTER:
5367 case GL_TEXTURE_MIN_FILTER:
5368 case GL_TEXTURE_WRAP_S:
5369 case GL_TEXTURE_WRAP_T:
5370 break;
5371
5372 case GL_TEXTURE_USAGE_ANGLE:
5373 if (!context->getExtensions().textureUsage)
5374 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005375 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005376 return false;
5377 }
5378 break;
5379
5380 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005381 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005382 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005383 return false;
5384 }
5385 break;
5386
5387 case GL_TEXTURE_IMMUTABLE_FORMAT:
5388 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5389 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005390 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005391 return false;
5392 }
5393 break;
5394
5395 case GL_TEXTURE_WRAP_R:
5396 case GL_TEXTURE_IMMUTABLE_LEVELS:
5397 case GL_TEXTURE_SWIZZLE_R:
5398 case GL_TEXTURE_SWIZZLE_G:
5399 case GL_TEXTURE_SWIZZLE_B:
5400 case GL_TEXTURE_SWIZZLE_A:
5401 case GL_TEXTURE_BASE_LEVEL:
5402 case GL_TEXTURE_MAX_LEVEL:
5403 case GL_TEXTURE_MIN_LOD:
5404 case GL_TEXTURE_MAX_LOD:
5405 case GL_TEXTURE_COMPARE_MODE:
5406 case GL_TEXTURE_COMPARE_FUNC:
5407 if (context->getClientMajorVersion() < 3)
5408 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005409 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Jamie Madillbe849e42017-05-02 15:49:00 -04005410 return false;
5411 }
5412 break;
5413
5414 case GL_TEXTURE_SRGB_DECODE_EXT:
5415 if (!context->getExtensions().textureSRGBDecode)
5416 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005417 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005418 return false;
5419 }
5420 break;
5421
Yunchao Hebacaa712018-01-30 14:01:39 +08005422 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5423 if (context->getClientVersion() < Version(3, 1))
5424 {
Jamie Madille0472f32018-11-27 16:32:45 -05005425 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Yunchao Hebacaa712018-01-30 14:01:39 +08005426 return false;
5427 }
5428 break;
5429
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005430 case GL_GENERATE_MIPMAP:
5431 case GL_TEXTURE_CROP_RECT_OES:
5432 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5433 // after GL_OES_draw_texture functionality implemented
5434 if (context->getClientMajorVersion() > 1)
5435 {
Jamie Madille0472f32018-11-27 16:32:45 -05005436 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005437 return false;
5438 }
5439 break;
Geoff Lang79b91402018-10-04 15:11:30 -04005440
5441 case GL_MEMORY_SIZE_ANGLE:
5442 if (!context->getExtensions().memorySize)
5443 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005444 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang79b91402018-10-04 15:11:30 -04005445 return false;
5446 }
5447 break;
5448
Till Rathmannb8543632018-10-02 19:46:14 +02005449 case GL_TEXTURE_BORDER_COLOR:
5450 if (!context->getExtensions().textureBorderClamp)
5451 {
Jamie Madille0472f32018-11-27 16:32:45 -05005452 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02005453 return false;
5454 }
5455 break;
5456
Jamie Madillbe849e42017-05-02 15:49:00 -04005457 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005458 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005459 return false;
5460 }
5461
5462 if (length)
5463 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005464 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005465 }
5466 return true;
5467}
5468
5469bool ValidateGetVertexAttribBase(Context *context,
5470 GLuint index,
5471 GLenum pname,
5472 GLsizei *length,
5473 bool pointer,
5474 bool pureIntegerEntryPoint)
5475{
5476 if (length)
5477 {
5478 *length = 0;
5479 }
5480
5481 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5482 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005483 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486
5487 if (index >= context->getCaps().maxVertexAttributes)
5488 {
Jamie Madille0472f32018-11-27 16:32:45 -05005489 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005490 return false;
5491 }
5492
5493 if (pointer)
5494 {
5495 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5496 {
Jamie Madille0472f32018-11-27 16:32:45 -05005497 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005498 return false;
5499 }
5500 }
5501 else
5502 {
5503 switch (pname)
5504 {
5505 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5506 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5507 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5508 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5509 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5510 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5511 case GL_CURRENT_VERTEX_ATTRIB:
5512 break;
5513
5514 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5515 static_assert(
5516 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5517 "ANGLE extension enums not equal to GL enums.");
5518 if (context->getClientMajorVersion() < 3 &&
5519 !context->getExtensions().instancedArrays)
5520 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005521 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005522 return false;
5523 }
5524 break;
5525
5526 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5527 if (context->getClientMajorVersion() < 3)
5528 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005529 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005530 return false;
5531 }
5532 break;
5533
5534 case GL_VERTEX_ATTRIB_BINDING:
5535 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5536 if (context->getClientVersion() < ES_3_1)
5537 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005538 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005539 return false;
5540 }
5541 break;
5542
5543 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005544 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005545 return false;
5546 }
5547 }
5548
5549 if (length)
5550 {
5551 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5552 {
5553 *length = 4;
5554 }
5555 else
5556 {
5557 *length = 1;
5558 }
5559 }
5560
5561 return true;
5562}
5563
Jamie Madill4928b7c2017-06-20 12:57:39 -04005564bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005565 GLint x,
5566 GLint y,
5567 GLsizei width,
5568 GLsizei height,
5569 GLenum format,
5570 GLenum type,
5571 GLsizei bufSize,
5572 GLsizei *length,
5573 GLsizei *columns,
5574 GLsizei *rows,
5575 void *pixels)
5576{
5577 if (length != nullptr)
5578 {
5579 *length = 0;
5580 }
5581 if (rows != nullptr)
5582 {
5583 *rows = 0;
5584 }
5585 if (columns != nullptr)
5586 {
5587 *columns = 0;
5588 }
5589
5590 if (width < 0 || height < 0)
5591 {
Jamie Madille0472f32018-11-27 16:32:45 -05005592 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005593 return false;
5594 }
5595
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005596 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005597
Jamie Madill427064d2018-04-13 16:20:34 -04005598 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005599 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005600 return false;
5601 }
5602
Jamie Madille98b1b52018-03-08 09:47:23 -05005603 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005604 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005605 return false;
5606 }
5607
Jamie Madill690c8eb2018-03-12 15:20:03 -04005608 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005609 ASSERT(framebuffer);
5610
5611 if (framebuffer->getReadBufferState() == GL_NONE)
5612 {
Jamie Madille0472f32018-11-27 16:32:45 -05005613 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005614 return false;
5615 }
5616
5617 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5618 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5619 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5620 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5621 // situation is an application error that would lead to a crash in ANGLE.
5622 if (readBuffer == nullptr)
5623 {
Jamie Madille0472f32018-11-27 16:32:45 -05005624 context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005625 return false;
5626 }
5627
Martin Radev28031682017-07-28 14:47:56 +03005628 // ANGLE_multiview, Revision 1:
5629 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005630 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5631 // in the current read framebuffer is more than one.
5632 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005633 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005634 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
Martin Radev28031682017-07-28 14:47:56 +03005635 return false;
5636 }
5637
Geoff Lang280ba992017-04-18 16:30:58 -04005638 if (context->getExtensions().webglCompatibility)
5639 {
5640 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5641 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5642 // and type before validating the combination of format and type. However, the
5643 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5644 // verifies that GL_INVALID_OPERATION is generated.
5645 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5646 // dEQP/WebGL.
5647 if (!ValidReadPixelsFormatEnum(context, format))
5648 {
Jamie Madille0472f32018-11-27 16:32:45 -05005649 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005650 return false;
5651 }
5652
5653 if (!ValidReadPixelsTypeEnum(context, type))
5654 {
Jamie Madille0472f32018-11-27 16:32:45 -05005655 context->validationError(GL_INVALID_ENUM, kInvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005656 return false;
5657 }
5658 }
5659
Jamie Madill690c8eb2018-03-12 15:20:03 -04005660 GLenum currentFormat = GL_NONE;
5661 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5662
5663 GLenum currentType = GL_NONE;
5664 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5665
Jamie Madillbe849e42017-05-02 15:49:00 -04005666 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5667
5668 bool validFormatTypeCombination =
5669 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5670
5671 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5672 {
Jamie Madille0472f32018-11-27 16:32:45 -05005673 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005674 return false;
5675 }
5676
5677 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005678 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005679 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5680 {
5681 // ...the buffer object's data store is currently mapped.
Jamie Madillc3e37312018-11-30 15:25:39 -05005682 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
Jamie Madillbe849e42017-05-02 15:49:00 -04005683 return false;
5684 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005685 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5686 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5687 {
Jamie Madille0472f32018-11-27 16:32:45 -05005688 context->validationError(GL_INVALID_OPERATION, kPixelPackBufferBoundForTransformFeedback);
James Darpiniane8a93c62018-01-04 18:02:24 -08005689 return false;
5690 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005691
5692 // .. the data would be packed to the buffer object such that the memory writes required
5693 // would exceed the data store size.
5694 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005695 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005696 const auto &pack = context->getGLState().getPackState();
5697
Jamie Madillca2ff382018-07-11 09:01:17 -04005698 GLuint endByte = 0;
5699 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005700 {
Jamie Madille0472f32018-11-27 16:32:45 -05005701 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005702 return false;
5703 }
5704
Jamie Madillbe849e42017-05-02 15:49:00 -04005705 if (bufSize >= 0)
5706 {
5707 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5708 {
Jamie Madille0472f32018-11-27 16:32:45 -05005709 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005710 return false;
5711 }
5712 }
5713
5714 if (pixelPackBuffer != nullptr)
5715 {
5716 CheckedNumeric<size_t> checkedEndByte(endByte);
5717 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5718 checkedEndByte += checkedOffset;
5719
5720 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5721 {
5722 // Overflow past the end of the buffer
Jamie Madille0472f32018-11-27 16:32:45 -05005723 context->validationError(GL_INVALID_OPERATION, kParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005724 return false;
5725 }
5726 }
5727
5728 if (pixelPackBuffer == nullptr && length != nullptr)
5729 {
5730 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5731 {
Jamie Madille0472f32018-11-27 16:32:45 -05005732 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005733 return false;
5734 }
5735
5736 *length = static_cast<GLsizei>(endByte);
5737 }
5738
Geoff Langa953b522018-02-21 16:56:23 -05005739 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005740 angle::CheckedNumeric<int> clippedExtent(length);
5741 if (start < 0)
5742 {
5743 // "subtract" the area that is less than 0
5744 clippedExtent += start;
5745 }
5746
Geoff Langa953b522018-02-21 16:56:23 -05005747 angle::CheckedNumeric<int> readExtent = start;
5748 readExtent += length;
5749 if (!readExtent.IsValid())
5750 {
5751 return false;
5752 }
5753
5754 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005755 {
5756 // Subtract the region to the right of the read buffer
5757 clippedExtent -= (readExtent - bufferSize);
5758 }
5759
5760 if (!clippedExtent.IsValid())
5761 {
Geoff Langa953b522018-02-21 16:56:23 -05005762 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005763 }
5764
Geoff Langa953b522018-02-21 16:56:23 -05005765 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5766 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005767 };
5768
Geoff Langa953b522018-02-21 16:56:23 -05005769 GLsizei writtenColumns = 0;
5770 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5771 {
Jamie Madille0472f32018-11-27 16:32:45 -05005772 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langa953b522018-02-21 16:56:23 -05005773 return false;
5774 }
5775
5776 GLsizei writtenRows = 0;
5777 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5778 {
Jamie Madille0472f32018-11-27 16:32:45 -05005779 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langa953b522018-02-21 16:56:23 -05005780 return false;
5781 }
5782
Jamie Madillbe849e42017-05-02 15:49:00 -04005783 if (columns != nullptr)
5784 {
Geoff Langa953b522018-02-21 16:56:23 -05005785 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005786 }
5787
5788 if (rows != nullptr)
5789 {
Geoff Langa953b522018-02-21 16:56:23 -05005790 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005791 }
5792
5793 return true;
5794}
5795
5796template <typename ParamType>
5797bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005798 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005799 GLenum pname,
5800 GLsizei bufSize,
Till Rathmannb8543632018-10-02 19:46:14 +02005801 bool vectorParams,
Jamie Madillbe849e42017-05-02 15:49:00 -04005802 const ParamType *params)
5803{
5804 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5805 {
Jamie Madille0472f32018-11-27 16:32:45 -05005806 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 return false;
5808 }
5809
5810 if (context->getTargetTexture(target) == nullptr)
5811 {
5812 // Should only be possible for external textures
Jamie Madille0472f32018-11-27 16:32:45 -05005813 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005814 return false;
5815 }
5816
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005817 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005818 if (bufSize >= 0 && bufSize < minBufSize)
5819 {
Jamie Madille0472f32018-11-27 16:32:45 -05005820 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005821 return false;
5822 }
5823
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005824 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5825 {
Jamie Madille0472f32018-11-27 16:32:45 -05005826 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005827 return false;
5828 }
5829
Jamie Madillbe849e42017-05-02 15:49:00 -04005830 switch (pname)
5831 {
5832 case GL_TEXTURE_WRAP_R:
5833 case GL_TEXTURE_SWIZZLE_R:
5834 case GL_TEXTURE_SWIZZLE_G:
5835 case GL_TEXTURE_SWIZZLE_B:
5836 case GL_TEXTURE_SWIZZLE_A:
5837 case GL_TEXTURE_BASE_LEVEL:
5838 case GL_TEXTURE_MAX_LEVEL:
5839 case GL_TEXTURE_COMPARE_MODE:
5840 case GL_TEXTURE_COMPARE_FUNC:
5841 case GL_TEXTURE_MIN_LOD:
5842 case GL_TEXTURE_MAX_LOD:
5843 if (context->getClientMajorVersion() < 3)
5844 {
Jamie Madille0472f32018-11-27 16:32:45 -05005845 context->validationError(GL_INVALID_ENUM, kES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005846 return false;
5847 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005848 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005849 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005850 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005851 return false;
5852 }
5853 break;
5854
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005855 case GL_GENERATE_MIPMAP:
5856 case GL_TEXTURE_CROP_RECT_OES:
5857 if (context->getClientMajorVersion() > 1)
5858 {
Jamie Madille0472f32018-11-27 16:32:45 -05005859 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005860 return false;
5861 }
5862 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005863 default:
5864 break;
5865 }
5866
Olli Etuahod310a432018-08-24 15:40:23 +03005867 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005868 {
5869 switch (pname)
5870 {
5871 case GL_TEXTURE_MIN_FILTER:
5872 case GL_TEXTURE_MAG_FILTER:
5873 case GL_TEXTURE_WRAP_S:
5874 case GL_TEXTURE_WRAP_T:
5875 case GL_TEXTURE_WRAP_R:
5876 case GL_TEXTURE_MIN_LOD:
5877 case GL_TEXTURE_MAX_LOD:
5878 case GL_TEXTURE_COMPARE_MODE:
5879 case GL_TEXTURE_COMPARE_FUNC:
Till Rathmannb8543632018-10-02 19:46:14 +02005880 case GL_TEXTURE_BORDER_COLOR:
Jamie Madillc3e37312018-11-30 15:25:39 -05005881 context->validationError(GL_INVALID_ENUM, kInvalidPname);
JiangYizhou4cff8d62017-07-06 14:54:09 +08005882 return false;
5883 }
5884 }
5885
Jamie Madillbe849e42017-05-02 15:49:00 -04005886 switch (pname)
5887 {
5888 case GL_TEXTURE_WRAP_S:
5889 case GL_TEXTURE_WRAP_T:
5890 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005891 {
5892 bool restrictedWrapModes =
5893 target == TextureType::External || target == TextureType::Rectangle;
5894 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005895 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005896 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005897 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005898 }
5899 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005900
5901 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005902 {
5903 bool restrictedMinFilter =
5904 target == TextureType::External || target == TextureType::Rectangle;
5905 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005906 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005907 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005908 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005909 }
5910 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005911
5912 case GL_TEXTURE_MAG_FILTER:
5913 if (!ValidateTextureMagFilterValue(context, params))
5914 {
5915 return false;
5916 }
5917 break;
5918
5919 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005920 if (!context->getExtensions().textureUsage)
5921 {
Jamie Madille0472f32018-11-27 16:32:45 -05005922 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang91ab54b2017-10-30 15:12:42 -04005923 return false;
5924 }
5925
Jamie Madillbe849e42017-05-02 15:49:00 -04005926 switch (ConvertToGLenum(params[0]))
5927 {
5928 case GL_NONE:
5929 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5930 break;
5931
5932 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005933 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005934 return false;
5935 }
5936 break;
5937
5938 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005939 {
5940 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5941 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005942 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005943 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005944 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005945 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5946 }
5947 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005948
5949 case GL_TEXTURE_MIN_LOD:
5950 case GL_TEXTURE_MAX_LOD:
5951 // any value is permissible
5952 break;
5953
5954 case GL_TEXTURE_COMPARE_MODE:
5955 if (!ValidateTextureCompareModeValue(context, params))
5956 {
5957 return false;
5958 }
5959 break;
5960
5961 case GL_TEXTURE_COMPARE_FUNC:
5962 if (!ValidateTextureCompareFuncValue(context, params))
5963 {
5964 return false;
5965 }
5966 break;
5967
5968 case GL_TEXTURE_SWIZZLE_R:
5969 case GL_TEXTURE_SWIZZLE_G:
5970 case GL_TEXTURE_SWIZZLE_B:
5971 case GL_TEXTURE_SWIZZLE_A:
5972 switch (ConvertToGLenum(params[0]))
5973 {
5974 case GL_RED:
5975 case GL_GREEN:
5976 case GL_BLUE:
5977 case GL_ALPHA:
5978 case GL_ZERO:
5979 case GL_ONE:
5980 break;
5981
5982 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005983 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005984 return false;
5985 }
5986 break;
5987
5988 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005989 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005990 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005991 context->validationError(GL_INVALID_VALUE, kBaseLevelNegative);
Jamie Madillbe849e42017-05-02 15:49:00 -04005992 return false;
5993 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005994 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005995 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005996 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04005997 return false;
5998 }
Olli Etuahod310a432018-08-24 15:40:23 +03005999 if ((target == TextureType::_2DMultisample ||
6000 target == TextureType::_2DMultisampleArray) &&
6001 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006002 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006003 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
JiangYizhou4cff8d62017-07-06 14:54:09 +08006004 return false;
6005 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006006 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006007 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006008 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006009 return false;
6010 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006011 break;
6012
6013 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006014 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006015 {
Jamie Madille0472f32018-11-27 16:32:45 -05006016 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006017 return false;
6018 }
6019 break;
6020
6021 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6022 if (context->getClientVersion() < Version(3, 1))
6023 {
Jamie Madille0472f32018-11-27 16:32:45 -05006024 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006025 return false;
6026 }
6027 switch (ConvertToGLenum(params[0]))
6028 {
6029 case GL_DEPTH_COMPONENT:
6030 case GL_STENCIL_INDEX:
6031 break;
6032
6033 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006034 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006035 return false;
6036 }
6037 break;
6038
6039 case GL_TEXTURE_SRGB_DECODE_EXT:
6040 if (!ValidateTextureSRGBDecodeValue(context, params))
6041 {
6042 return false;
6043 }
6044 break;
6045
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006046 case GL_GENERATE_MIPMAP:
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006047 if (context->getClientMajorVersion() > 1)
6048 {
Jamie Madille0472f32018-11-27 16:32:45 -05006049 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006050 return false;
6051 }
6052 break;
Till Rathmannb8543632018-10-02 19:46:14 +02006053
6054 case GL_TEXTURE_CROP_RECT_OES:
6055 if (context->getClientMajorVersion() > 1)
6056 {
Jamie Madille0472f32018-11-27 16:32:45 -05006057 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Till Rathmannb8543632018-10-02 19:46:14 +02006058 return false;
6059 }
6060 if (!vectorParams)
6061 {
Jamie Madille0472f32018-11-27 16:32:45 -05006062 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006063 return false;
6064 }
6065 break;
6066
6067 case GL_TEXTURE_BORDER_COLOR:
6068 if (!context->getExtensions().textureBorderClamp)
6069 {
Jamie Madille0472f32018-11-27 16:32:45 -05006070 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006071 return false;
6072 }
6073 if (!vectorParams)
6074 {
Jamie Madille0472f32018-11-27 16:32:45 -05006075 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006076 return false;
6077 }
6078 break;
6079
Jamie Madillbe849e42017-05-02 15:49:00 -04006080 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006081 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006082 return false;
6083 }
6084
6085 return true;
6086}
6087
Till Rathmannb8543632018-10-02 19:46:14 +02006088template bool ValidateTexParameterBase(Context *,
6089 TextureType,
6090 GLenum,
6091 GLsizei,
6092 bool,
6093 const GLfloat *);
6094template bool ValidateTexParameterBase(Context *,
6095 TextureType,
6096 GLenum,
6097 GLsizei,
6098 bool,
6099 const GLint *);
6100template bool ValidateTexParameterBase(Context *,
6101 TextureType,
6102 GLenum,
6103 GLsizei,
6104 bool,
6105 const GLuint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006106
Jamie Madill5b772312018-03-08 20:28:32 -05006107bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006108{
6109 if (index >= MAX_VERTEX_ATTRIBS)
6110 {
Jamie Madille0472f32018-11-27 16:32:45 -05006111 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Jamie Madill12e957f2017-08-26 21:42:26 -04006112 return false;
6113 }
6114
6115 return true;
6116}
6117
6118bool ValidateGetActiveUniformBlockivBase(Context *context,
6119 GLuint program,
6120 GLuint uniformBlockIndex,
6121 GLenum pname,
6122 GLsizei *length)
6123{
6124 if (length)
6125 {
6126 *length = 0;
6127 }
6128
6129 if (context->getClientMajorVersion() < 3)
6130 {
Jamie Madille0472f32018-11-27 16:32:45 -05006131 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill12e957f2017-08-26 21:42:26 -04006132 return false;
6133 }
6134
6135 Program *programObject = GetValidProgram(context, program);
6136 if (!programObject)
6137 {
6138 return false;
6139 }
6140
6141 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6142 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006143 context->validationError(GL_INVALID_VALUE, kIndexExceedsActiveUniformBlockCount);
Jamie Madill12e957f2017-08-26 21:42:26 -04006144 return false;
6145 }
6146
6147 switch (pname)
6148 {
6149 case GL_UNIFORM_BLOCK_BINDING:
6150 case GL_UNIFORM_BLOCK_DATA_SIZE:
6151 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6152 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6153 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6154 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6155 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6156 break;
6157
6158 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006159 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill12e957f2017-08-26 21:42:26 -04006160 return false;
6161 }
6162
6163 if (length)
6164 {
6165 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6166 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006167 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006168 programObject->getUniformBlockByIndex(uniformBlockIndex);
6169 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6170 }
6171 else
6172 {
6173 *length = 1;
6174 }
6175 }
6176
6177 return true;
6178}
6179
Jamie Madill9696d072017-08-26 23:19:57 -04006180template <typename ParamType>
6181bool ValidateSamplerParameterBase(Context *context,
6182 GLuint sampler,
6183 GLenum pname,
6184 GLsizei bufSize,
Till Rathmannb8543632018-10-02 19:46:14 +02006185 bool vectorParams,
Jamie Madill9696d072017-08-26 23:19:57 -04006186 ParamType *params)
6187{
6188 if (context->getClientMajorVersion() < 3)
6189 {
Jamie Madille0472f32018-11-27 16:32:45 -05006190 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006191 return false;
6192 }
6193
6194 if (!context->isSampler(sampler))
6195 {
Jamie Madille0472f32018-11-27 16:32:45 -05006196 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
Jamie Madill9696d072017-08-26 23:19:57 -04006197 return false;
6198 }
6199
Till Rathmannb8543632018-10-02 19:46:14 +02006200 const GLsizei minBufSize = GetSamplerParameterCount(pname);
Jamie Madill9696d072017-08-26 23:19:57 -04006201 if (bufSize >= 0 && bufSize < minBufSize)
6202 {
Jamie Madille0472f32018-11-27 16:32:45 -05006203 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madill9696d072017-08-26 23:19:57 -04006204 return false;
6205 }
6206
6207 switch (pname)
6208 {
6209 case GL_TEXTURE_WRAP_S:
6210 case GL_TEXTURE_WRAP_T:
6211 case GL_TEXTURE_WRAP_R:
6212 if (!ValidateTextureWrapModeValue(context, params, false))
6213 {
6214 return false;
6215 }
6216 break;
6217
6218 case GL_TEXTURE_MIN_FILTER:
6219 if (!ValidateTextureMinFilterValue(context, params, false))
6220 {
6221 return false;
6222 }
6223 break;
6224
6225 case GL_TEXTURE_MAG_FILTER:
6226 if (!ValidateTextureMagFilterValue(context, params))
6227 {
6228 return false;
6229 }
6230 break;
6231
6232 case GL_TEXTURE_MIN_LOD:
6233 case GL_TEXTURE_MAX_LOD:
6234 // any value is permissible
6235 break;
6236
6237 case GL_TEXTURE_COMPARE_MODE:
6238 if (!ValidateTextureCompareModeValue(context, params))
6239 {
6240 return false;
6241 }
6242 break;
6243
6244 case GL_TEXTURE_COMPARE_FUNC:
6245 if (!ValidateTextureCompareFuncValue(context, params))
6246 {
6247 return false;
6248 }
6249 break;
6250
6251 case GL_TEXTURE_SRGB_DECODE_EXT:
6252 if (!ValidateTextureSRGBDecodeValue(context, params))
6253 {
6254 return false;
6255 }
6256 break;
6257
Luc Ferron1b1a8642018-01-23 15:12:01 -05006258 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6259 {
6260 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6261 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6262 {
6263 return false;
6264 }
6265 }
6266 break;
6267
Till Rathmannb8543632018-10-02 19:46:14 +02006268 case GL_TEXTURE_BORDER_COLOR:
6269 if (!context->getExtensions().textureBorderClamp)
6270 {
Jamie Madille0472f32018-11-27 16:32:45 -05006271 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006272 return false;
6273 }
6274 if (!vectorParams)
6275 {
Jamie Madille0472f32018-11-27 16:32:45 -05006276 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006277 return false;
6278 }
6279 break;
6280
Jamie Madill9696d072017-08-26 23:19:57 -04006281 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006282 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006283 return false;
6284 }
6285
6286 return true;
6287}
6288
Till Rathmannb8543632018-10-02 19:46:14 +02006289template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, bool, GLfloat *);
6290template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, bool, GLint *);
6291template bool ValidateSamplerParameterBase(Context *,
6292 GLuint,
6293 GLenum,
6294 GLsizei,
6295 bool,
6296 const GLuint *);
Jamie Madill9696d072017-08-26 23:19:57 -04006297
6298bool ValidateGetSamplerParameterBase(Context *context,
6299 GLuint sampler,
6300 GLenum pname,
6301 GLsizei *length)
6302{
6303 if (length)
6304 {
6305 *length = 0;
6306 }
6307
6308 if (context->getClientMajorVersion() < 3)
6309 {
Jamie Madille0472f32018-11-27 16:32:45 -05006310 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006311 return false;
6312 }
6313
6314 if (!context->isSampler(sampler))
6315 {
Jamie Madille0472f32018-11-27 16:32:45 -05006316 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
Jamie Madill9696d072017-08-26 23:19:57 -04006317 return false;
6318 }
6319
6320 switch (pname)
6321 {
6322 case GL_TEXTURE_WRAP_S:
6323 case GL_TEXTURE_WRAP_T:
6324 case GL_TEXTURE_WRAP_R:
6325 case GL_TEXTURE_MIN_FILTER:
6326 case GL_TEXTURE_MAG_FILTER:
6327 case GL_TEXTURE_MIN_LOD:
6328 case GL_TEXTURE_MAX_LOD:
6329 case GL_TEXTURE_COMPARE_MODE:
6330 case GL_TEXTURE_COMPARE_FUNC:
6331 break;
6332
Luc Ferron1b1a8642018-01-23 15:12:01 -05006333 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6334 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6335 {
6336 return false;
6337 }
6338 break;
6339
Jamie Madill9696d072017-08-26 23:19:57 -04006340 case GL_TEXTURE_SRGB_DECODE_EXT:
6341 if (!context->getExtensions().textureSRGBDecode)
6342 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006343 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006344 return false;
6345 }
6346 break;
6347
Till Rathmannb8543632018-10-02 19:46:14 +02006348 case GL_TEXTURE_BORDER_COLOR:
6349 if (!context->getExtensions().textureBorderClamp)
6350 {
Jamie Madille0472f32018-11-27 16:32:45 -05006351 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006352 return false;
6353 }
6354 break;
6355
Jamie Madill9696d072017-08-26 23:19:57 -04006356 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006357 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006358 return false;
6359 }
6360
6361 if (length)
6362 {
Till Rathmannb8543632018-10-02 19:46:14 +02006363 *length = GetSamplerParameterCount(pname);
Jamie Madill9696d072017-08-26 23:19:57 -04006364 }
6365 return true;
6366}
6367
6368bool ValidateGetInternalFormativBase(Context *context,
6369 GLenum target,
6370 GLenum internalformat,
6371 GLenum pname,
6372 GLsizei bufSize,
6373 GLsizei *numParams)
6374{
6375 if (numParams)
6376 {
6377 *numParams = 0;
6378 }
6379
6380 if (context->getClientMajorVersion() < 3)
6381 {
Jamie Madille0472f32018-11-27 16:32:45 -05006382 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006383 return false;
6384 }
6385
6386 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006387 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006388 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006389 context->validationError(GL_INVALID_ENUM, kFormatNotRenderable);
Jamie Madill9696d072017-08-26 23:19:57 -04006390 return false;
6391 }
6392
6393 switch (target)
6394 {
6395 case GL_RENDERBUFFER:
6396 break;
6397
6398 case GL_TEXTURE_2D_MULTISAMPLE:
Yizhou Jiang7818a852018-09-06 15:02:04 +08006399 if (context->getClientVersion() < ES_3_1 &&
6400 !context->getExtensions().textureMultisample)
Jamie Madill9696d072017-08-26 23:19:57 -04006401 {
Jamie Madill610640f2018-11-21 17:28:41 -05006402 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05006403 kMultisampleTextureExtensionOrES31Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006404 return false;
6405 }
6406 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006407 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6408 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006409 {
Jamie Madille0472f32018-11-27 16:32:45 -05006410 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
Olli Etuahod310a432018-08-24 15:40:23 +03006411 return false;
6412 }
6413 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006414 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006415 context->validationError(GL_INVALID_ENUM, kInvalidTarget);
Jamie Madill9696d072017-08-26 23:19:57 -04006416 return false;
6417 }
6418
6419 if (bufSize < 0)
6420 {
Jamie Madille0472f32018-11-27 16:32:45 -05006421 context->validationError(GL_INVALID_VALUE, kInsufficientBufferSize);
Jamie Madill9696d072017-08-26 23:19:57 -04006422 return false;
6423 }
6424
6425 GLsizei maxWriteParams = 0;
6426 switch (pname)
6427 {
6428 case GL_NUM_SAMPLE_COUNTS:
6429 maxWriteParams = 1;
6430 break;
6431
6432 case GL_SAMPLES:
6433 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6434 break;
6435
6436 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006437 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006438 return false;
6439 }
6440
6441 if (numParams)
6442 {
6443 // glGetInternalFormativ will not overflow bufSize
6444 *numParams = std::min(bufSize, maxWriteParams);
6445 }
6446
6447 return true;
6448}
6449
Jamie Madille98b1b52018-03-08 09:47:23 -05006450bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6451{
Jamie Madill427064d2018-04-13 16:20:34 -04006452 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006453 {
Jamie Madille0472f32018-11-27 16:32:45 -05006454 context->validationError(GL_INVALID_OPERATION, kInvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006455 return false;
6456 }
6457 return true;
6458}
6459
Lingfeng Yang038dd532018-03-29 17:31:52 -07006460bool ValidateMultitextureUnit(Context *context, GLenum texture)
6461{
6462 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6463 {
Jamie Madille0472f32018-11-27 16:32:45 -05006464 context->validationError(GL_INVALID_ENUM, kInvalidMultitextureUnit);
Lingfeng Yang038dd532018-03-29 17:31:52 -07006465 return false;
6466 }
6467 return true;
6468}
6469
Olli Etuahod310a432018-08-24 15:40:23 +03006470bool ValidateTexStorageMultisample(Context *context,
6471 TextureType target,
6472 GLsizei samples,
6473 GLint internalFormat,
6474 GLsizei width,
6475 GLsizei height)
6476{
6477 const Caps &caps = context->getCaps();
6478 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6479 static_cast<GLuint>(height) > caps.max2DTextureSize)
6480 {
Jamie Madille0472f32018-11-27 16:32:45 -05006481 context->validationError(GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
Olli Etuahod310a432018-08-24 15:40:23 +03006482 return false;
6483 }
6484
6485 if (samples == 0)
6486 {
Jamie Madille0472f32018-11-27 16:32:45 -05006487 context->validationError(GL_INVALID_VALUE, kSamplesZero);
Olli Etuahod310a432018-08-24 15:40:23 +03006488 return false;
6489 }
6490
6491 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6492 if (!formatCaps.textureAttachment)
6493 {
Jamie Madille0472f32018-11-27 16:32:45 -05006494 context->validationError(GL_INVALID_ENUM, kRenderableInternalFormat);
Olli Etuahod310a432018-08-24 15:40:23 +03006495 return false;
6496 }
6497
6498 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6499 // is one of the unsized base internalformats listed in table 8.11.
6500 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6501 if (formatInfo.internalFormat == GL_NONE)
6502 {
Jamie Madille0472f32018-11-27 16:32:45 -05006503 context->validationError(GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
Olli Etuahod310a432018-08-24 15:40:23 +03006504 return false;
6505 }
6506
6507 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6508 {
Jamie Madille0472f32018-11-27 16:32:45 -05006509 context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
Olli Etuahod310a432018-08-24 15:40:23 +03006510 return false;
6511 }
6512
6513 Texture *texture = context->getTargetTexture(target);
6514 if (!texture || texture->id() == 0)
6515 {
Jamie Madille0472f32018-11-27 16:32:45 -05006516 context->validationError(GL_INVALID_OPERATION, kZeroBoundToTarget);
Olli Etuahod310a432018-08-24 15:40:23 +03006517 return false;
6518 }
6519
6520 if (texture->getImmutableFormat())
6521 {
Jamie Madille0472f32018-11-27 16:32:45 -05006522 context->validationError(GL_INVALID_OPERATION, kImmutableTextureBound);
Olli Etuahod310a432018-08-24 15:40:23 +03006523 return false;
6524 }
6525 return true;
6526}
6527
Yizhou Jiang7818a852018-09-06 15:02:04 +08006528bool ValidateTexStorage2DMultisampleBase(Context *context,
6529 TextureType target,
6530 GLsizei samples,
6531 GLint internalFormat,
6532 GLsizei width,
6533 GLsizei height)
6534{
6535 if (target != TextureType::_2DMultisample)
6536 {
Jamie Madille0472f32018-11-27 16:32:45 -05006537 context->validationError(GL_INVALID_ENUM, kInvalidTarget);
Yizhou Jiang7818a852018-09-06 15:02:04 +08006538 return false;
6539 }
6540
6541 if (width < 1 || height < 1)
6542 {
Jamie Madille0472f32018-11-27 16:32:45 -05006543 context->validationError(GL_INVALID_VALUE, kTextureSizeTooSmall);
Yizhou Jiang7818a852018-09-06 15:02:04 +08006544 return false;
6545 }
6546
6547 return ValidateTexStorageMultisample(context, target, samples, internalFormat, width, height);
6548}
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006549
6550bool ValidateGetTexLevelParameterBase(Context *context,
6551 TextureTarget target,
6552 GLint level,
6553 GLenum pname,
6554 GLsizei *length)
6555{
6556
6557 if (length)
6558 {
6559 *length = 0;
6560 }
6561
6562 TextureType type = TextureTargetToType(target);
6563
6564 if (!ValidTexLevelDestinationTarget(context, type))
6565 {
Jamie Madille0472f32018-11-27 16:32:45 -05006566 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006567 return false;
6568 }
6569
6570 if (context->getTargetTexture(type) == nullptr)
6571 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006572 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006573 return false;
6574 }
6575
6576 if (!ValidMipLevel(context, type, level))
6577 {
Jamie Madille0472f32018-11-27 16:32:45 -05006578 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006579 return false;
6580 }
6581
6582 switch (pname)
6583 {
6584 case GL_TEXTURE_RED_TYPE:
6585 case GL_TEXTURE_GREEN_TYPE:
6586 case GL_TEXTURE_BLUE_TYPE:
6587 case GL_TEXTURE_ALPHA_TYPE:
6588 case GL_TEXTURE_DEPTH_TYPE:
6589 break;
6590 case GL_TEXTURE_RED_SIZE:
6591 case GL_TEXTURE_GREEN_SIZE:
6592 case GL_TEXTURE_BLUE_SIZE:
6593 case GL_TEXTURE_ALPHA_SIZE:
6594 case GL_TEXTURE_DEPTH_SIZE:
6595 case GL_TEXTURE_STENCIL_SIZE:
6596 case GL_TEXTURE_SHARED_SIZE:
6597 break;
6598 case GL_TEXTURE_INTERNAL_FORMAT:
6599 case GL_TEXTURE_WIDTH:
6600 case GL_TEXTURE_HEIGHT:
6601 case GL_TEXTURE_DEPTH:
6602 break;
6603 case GL_TEXTURE_SAMPLES:
6604 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
6605 break;
6606 case GL_TEXTURE_COMPRESSED:
6607 break;
6608 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006609 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006610 return false;
6611 }
6612
6613 if (length)
6614 {
6615 *length = 1;
6616 }
6617 return true;
6618}
Yizhou Jiang7310da32018-11-05 14:40:01 +08006619
6620bool ValidateGetMultisamplefvBase(Context *context, GLenum pname, GLuint index, GLfloat *val)
6621{
6622 if (pname != GL_SAMPLE_POSITION)
6623 {
6624 context->validationError(GL_INVALID_ENUM, kInvalidPname);
6625 return false;
6626 }
6627
6628 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
6629 GLint samples = framebuffer->getSamples(context);
6630
6631 if (index >= static_cast<GLuint>(samples))
6632 {
6633 context->validationError(GL_INVALID_VALUE, kIndexExceedsSamples);
6634 return false;
6635 }
6636
6637 return true;
6638}
6639
6640bool ValidateSampleMaskiBase(Context *context, GLuint maskNumber, GLbitfield mask)
6641{
6642 if (maskNumber >= context->getCaps().maxSampleMaskWords)
6643 {
6644 context->validationError(GL_INVALID_VALUE, kInvalidSampleMaskNumber);
6645 return false;
6646 }
6647
6648 return true;
6649}
Jamie Madillc29968b2016-01-20 11:17:23 -05006650} // namespace gl