blob: 9170c07b5a8056c3036f5290569b643a75afead4 [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;
Geoff Langbe607ad2018-11-29 10:14:22 -0500763
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800764 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800765 maxDimension = caps.maxCubeMapTextureSize;
766 break;
Geoff Langbe607ad2018-11-29 10:14:22 -0500767
768 case TextureType::External:
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800769 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400770 return level == 0;
Geoff Langbe607ad2018-11-29 10:14:22 -0500771
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800772 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800773 maxDimension = caps.max3DTextureSize;
774 break;
Geoff Langbe607ad2018-11-29 10:14:22 -0500775
He Yunchaoced53ae2016-11-29 15:00:51 +0800776 default:
777 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400778 }
779
Jamie Madill43da7c42018-08-01 11:34:49 -0400780 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400781}
782
Jamie Madill5b772312018-03-08 20:28:32 -0500783bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800784 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700785 GLint level,
786 GLsizei width,
787 GLsizei height,
788 GLsizei depth,
789 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400790{
Brandon Jones6cad5662017-06-14 13:25:13 -0700791 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400792 {
Jamie Madille0472f32018-11-27 16:32:45 -0500793 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400794 return false;
795 }
Austin Kinross08528e12015-10-07 16:24:40 -0700796 // TexSubImage parameters can be NPOT without textureNPOT extension,
797 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500798 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500799 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500800 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400801 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400802 {
Jamie Madille0472f32018-11-27 16:32:45 -0500803 context->validationError(GL_INVALID_VALUE, kTextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400804 return false;
805 }
806
807 if (!ValidMipLevel(context, target, level))
808 {
Jamie Madille0472f32018-11-27 16:32:45 -0500809 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400810 return false;
811 }
812
813 return true;
814}
815
Geoff Lang966c9402017-04-18 12:38:27 -0400816bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
817{
818 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
819 (size % blockSize == 0);
820}
821
Jamie Madill5b772312018-03-08 20:28:32 -0500822bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500823 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400824 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500825 GLsizei width,
826 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400827{
Jamie Madill43da7c42018-08-01 11:34:49 -0400828 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400829 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400830 {
831 return false;
832 }
833
Geoff Lang966c9402017-04-18 12:38:27 -0400834 if (width < 0 || height < 0)
835 {
836 return false;
837 }
838
839 if (CompressedTextureFormatRequiresExactSize(internalFormat))
840 {
841 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
842 // block size for level 0 but WebGL disallows this.
843 bool smallerThanBlockSizeAllowed =
844 level > 0 || !context->getExtensions().webglCompatibility;
845
846 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
847 smallerThanBlockSizeAllowed) ||
848 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
849 smallerThanBlockSizeAllowed))
850 {
851 return false;
852 }
853 }
854
855 return true;
856}
857
Jamie Madill5b772312018-03-08 20:28:32 -0500858bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400859 GLenum internalFormat,
860 GLint xoffset,
861 GLint yoffset,
862 GLsizei width,
863 GLsizei height,
864 size_t textureWidth,
865 size_t textureHeight)
866{
Jamie Madill43da7c42018-08-01 11:34:49 -0400867 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400868 if (!formatInfo.compressed)
869 {
870 return false;
871 }
872
Geoff Lang44ff5a72017-02-03 15:15:43 -0500873 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400874 {
875 return false;
876 }
877
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500878 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400879 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500880 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400881 yoffset % formatInfo.compressedBlockHeight != 0)
882 {
883 return false;
884 }
885
886 // Allowed to either have data that is a multiple of block size or is smaller than the block
887 // size but fills the entire mip
888 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
889 static_cast<size_t>(width) == textureWidth &&
890 static_cast<size_t>(height) == textureHeight;
891 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
892 (height % formatInfo.compressedBlockHeight) == 0;
893 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400894 {
895 return false;
896 }
897 }
898
Geoff Langd4f180b2013-09-24 13:57:44 -0400899 return true;
900}
901
Jamie Madill5b772312018-03-08 20:28:32 -0500902bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800903 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400904 GLsizei width,
905 GLsizei height,
906 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400907 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400908 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400909 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400910 GLsizei imageSize)
911{
Jamie Madill43da7c42018-08-01 11:34:49 -0400912 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400913 if (pixelUnpackBuffer == nullptr && imageSize < 0)
914 {
915 // Checks are not required
916 return true;
917 }
918
919 // ...the data would be unpacked from the buffer object such that the memory reads required
920 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400921 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400922 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400923 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400924 const auto &unpack = context->getGLState().getUnpackState();
925
Jamie Madill7f232932018-09-12 11:03:06 -0400926 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
927 GLuint endByte = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400928 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400929 {
Jamie Madille0472f32018-11-27 16:32:45 -0500930 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400931 return false;
932 }
933
Geoff Langff5b2d52016-09-07 11:32:23 -0400934 if (pixelUnpackBuffer)
935 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400936 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400937 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
938 checkedEndByte += checkedOffset;
939
940 if (!checkedEndByte.IsValid() ||
941 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
942 {
943 // Overflow past the end of the buffer
Jamie Madille0472f32018-11-27 16:32:45 -0500944 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400945 return false;
946 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800947 if (context->getExtensions().webglCompatibility &&
948 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
949 {
Jamie Madill610640f2018-11-21 17:28:41 -0500950 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -0500951 kPixelUnpackBufferBoundForTransformFeedback);
James Darpiniane8a93c62018-01-04 18:02:24 -0800952 return false;
953 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400954 }
955 else
956 {
957 ASSERT(imageSize >= 0);
958 if (pixels == nullptr && imageSize != 0)
959 {
Jamie Madillc3e37312018-11-30 15:25:39 -0500960 context->validationError(GL_INVALID_OPERATION, kImageSizeMustBeZero);
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400961 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400962 }
963
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400964 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400965 {
Jamie Madillc3e37312018-11-30 15:25:39 -0500966 context->validationError(GL_INVALID_OPERATION, kImageSizeTooSmall);
Geoff Langff5b2d52016-09-07 11:32:23 -0400967 return false;
968 }
969 }
970
971 return true;
972}
973
Corentin Wallezad3ae902018-03-09 13:40:42 -0500974bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500975{
Geoff Lang37dde692014-01-31 16:34:54 -0500976 switch (queryType)
977 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500978 case QueryType::AnySamples:
979 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400980 return context->getClientMajorVersion() >= 3 ||
981 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500982 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800983 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500984 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500986 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800987 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500988 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800989 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800990 default:
991 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500992 }
993}
994
Jamie Madill5b772312018-03-08 20:28:32 -0500995bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400996 GLenum type,
997 GLboolean normalized,
998 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400999 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001000 bool pureInteger)
1001{
1002 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001003 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1004 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1005 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1006 // parameter exceeds 255.
1007 constexpr GLsizei kMaxWebGLStride = 255;
1008 if (stride > kMaxWebGLStride)
1009 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001010 context->validationError(GL_INVALID_VALUE, kStrideExceedsWebGLLimit);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001011 return false;
1012 }
1013
1014 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1015 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1016 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1017 // or an INVALID_OPERATION error is generated.
Frank Henigmand633b152018-10-04 23:34:31 -04001018 angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
1019 size_t typeSize = GetVertexFormatSize(internalType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001020
1021 ASSERT(isPow2(typeSize) && typeSize > 0);
1022 size_t sizeMask = (typeSize - 1);
1023 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1024 {
Jamie Madille0472f32018-11-27 16:32:45 -05001025 context->validationError(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001026 return false;
1027 }
1028
1029 if ((stride & sizeMask) != 0)
1030 {
Jamie Madille0472f32018-11-27 16:32:45 -05001031 context->validationError(GL_INVALID_OPERATION, kStrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001032 return false;
1033 }
1034
1035 return true;
1036}
1037
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001038Program *GetValidProgramNoResolve(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001039{
He Yunchaoced53ae2016-11-29 15:00:51 +08001040 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1041 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1042 // or program object and INVALID_OPERATION if the provided name identifies an object
1043 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001044
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001045 Program *validProgram = context->getProgramNoResolveLink(id);
Dian Xiang769769a2015-09-09 15:20:08 -07001046
1047 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001048 {
Dian Xiang769769a2015-09-09 15:20:08 -07001049 if (context->getShader(id))
1050 {
Jamie Madille0472f32018-11-27 16:32:45 -05001051 context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001052 }
1053 else
1054 {
Jamie Madille0472f32018-11-27 16:32:45 -05001055 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001056 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001057 }
Dian Xiang769769a2015-09-09 15:20:08 -07001058
1059 return validProgram;
1060}
1061
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001062Program *GetValidProgram(Context *context, GLuint id)
1063{
1064 Program *program = GetValidProgramNoResolve(context, id);
1065 if (program)
1066 {
Jamie Madill785e8a02018-10-04 17:42:00 -04001067 program->resolveLink(context);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001068 }
1069 return program;
1070}
1071
Jamie Madill5b772312018-03-08 20:28:32 -05001072Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001073{
1074 // See ValidProgram for spec details.
1075
1076 Shader *validShader = context->getShader(id);
1077
1078 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001079 {
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001080 if (context->getProgramNoResolveLink(id))
Dian Xiang769769a2015-09-09 15:20:08 -07001081 {
Jamie Madille0472f32018-11-27 16:32:45 -05001082 context->validationError(GL_INVALID_OPERATION, kExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001083 }
1084 else
1085 {
Jamie Madille0472f32018-11-27 16:32:45 -05001086 context->validationError(GL_INVALID_VALUE, kInvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001087 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001088 }
Dian Xiang769769a2015-09-09 15:20:08 -07001089
1090 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001091}
1092
Jamie Madill43da7c42018-08-01 11:34:49 -04001093bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001094{
Geoff Langfa125c92017-10-24 13:01:46 -04001095 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001096 {
Geoff Langfa125c92017-10-24 13:01:46 -04001097 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1098 {
Jamie Madille0472f32018-11-27 16:32:45 -05001099 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langfa125c92017-10-24 13:01:46 -04001100 return false;
1101 }
Jamie Madillb4472272014-07-03 10:38:55 -04001102
Geoff Langfa125c92017-10-24 13:01:46 -04001103 // Color attachment 0 is validated below because it is always valid
1104 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001105 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001106 {
Jamie Madille0472f32018-11-27 16:32:45 -05001107 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001108 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001109 }
1110 }
1111 else
1112 {
1113 switch (attachment)
1114 {
Geoff Langfa125c92017-10-24 13:01:46 -04001115 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001116 case GL_DEPTH_ATTACHMENT:
1117 case GL_STENCIL_ATTACHMENT:
1118 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001119
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 case GL_DEPTH_STENCIL_ATTACHMENT:
1121 if (!context->getExtensions().webglCompatibility &&
1122 context->getClientMajorVersion() < 3)
1123 {
Jamie Madille0472f32018-11-27 16:32:45 -05001124 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001125 return false;
1126 }
1127 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001128
He Yunchaoced53ae2016-11-29 15:00:51 +08001129 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001130 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001131 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001132 }
1133 }
1134
1135 return true;
1136}
1137
Jamie Madill5b772312018-03-08 20:28:32 -05001138bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001139 GLenum target,
1140 GLsizei samples,
1141 GLenum internalformat,
1142 GLsizei width,
1143 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001144{
1145 switch (target)
1146 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001147 case GL_RENDERBUFFER:
1148 break;
1149 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001150 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001151 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001152 }
1153
1154 if (width < 0 || height < 0 || samples < 0)
1155 {
Jamie Madille0472f32018-11-27 16:32:45 -05001156 context->validationError(GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001158 }
1159
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001160 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1161 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1162
1163 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001164 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001165 {
Jamie Madille0472f32018-11-27 16:32:45 -05001166 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001167 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001168 }
1169
1170 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1171 // 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 -08001172 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001173 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001174 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001175 {
Jamie Madille0472f32018-11-27 16:32:45 -05001176 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001177 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001178 }
1179
Geoff Langaae65a42014-05-26 12:43:44 -04001180 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001181 {
Jamie Madille0472f32018-11-27 16:32:45 -05001182 context->validationError(GL_INVALID_VALUE, kResourceMaxRenderbufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04001183 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001184 }
1185
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001186 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001187 if (handle == 0)
1188 {
Jamie Madille0472f32018-11-27 16:32:45 -05001189 context->validationError(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001190 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001191 }
1192
1193 return true;
1194}
1195
Jamie Madill43da7c42018-08-01 11:34:49 -04001196bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001197 GLenum target,
1198 GLenum attachment,
1199 GLenum renderbuffertarget,
1200 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001201{
Geoff Lange8afa902017-09-27 15:00:43 -04001202 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001203 {
Jamie Madille0472f32018-11-27 16:32:45 -05001204 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001205 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001206 }
1207
Jamie Madill43da7c42018-08-01 11:34:49 -04001208 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001209
Jamie Madill84115c92015-04-23 15:00:07 -04001210 ASSERT(framebuffer);
1211 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001212 {
Jamie Madille0472f32018-11-27 16:32:45 -05001213 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001214 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001215 }
1216
Jamie Madillb4472272014-07-03 10:38:55 -04001217 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001218 {
Jamie Madillb4472272014-07-03 10:38:55 -04001219 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001220 }
1221
Jamie Madillab9d82c2014-01-21 16:38:14 -05001222 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1223 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1224 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1225 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1226 if (renderbuffer != 0)
1227 {
1228 if (!context->getRenderbuffer(renderbuffer))
1229 {
Jamie Madille0472f32018-11-27 16:32:45 -05001230 context->validationError(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001232 }
1233 }
1234
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001235 return true;
1236}
1237
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001238bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001239 GLint srcX0,
1240 GLint srcY0,
1241 GLint srcX1,
1242 GLint srcY1,
1243 GLint dstX0,
1244 GLint dstY0,
1245 GLint dstX1,
1246 GLint dstY1,
1247 GLbitfield mask,
1248 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001249{
1250 switch (filter)
1251 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001252 case GL_NEAREST:
1253 break;
1254 case GL_LINEAR:
1255 break;
1256 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001257 context->validationError(GL_INVALID_ENUM, kBlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001258 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001259 }
1260
1261 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1262 {
Jamie Madille0472f32018-11-27 16:32:45 -05001263 context->validationError(GL_INVALID_VALUE, kBlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001264 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001265 }
1266
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001267 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1268 // color buffer, leaving only nearest being unfiltered from above
1269 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1270 {
Jamie Madille0472f32018-11-27 16:32:45 -05001271 context->validationError(GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001272 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001273 }
1274
Jamie Madill7f232932018-09-12 11:03:06 -04001275 const auto &glState = context->getGLState();
1276 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1277 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001278
1279 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280 {
Jamie Madille0472f32018-11-27 16:32:45 -05001281 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001282 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001283 }
1284
Jamie Madill427064d2018-04-13 16:20:34 -04001285 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001286 {
Jamie Madill48faf802014-11-06 15:27:22 -05001287 return false;
1288 }
1289
Jamie Madill427064d2018-04-13 16:20:34 -04001290 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001291 {
Jamie Madill48faf802014-11-06 15:27:22 -05001292 return false;
1293 }
1294
Qin Jiajiaaef92162018-02-27 13:51:44 +08001295 if (readFramebuffer->id() == drawFramebuffer->id())
1296 {
Jamie Madille0472f32018-11-27 16:32:45 -05001297 context->validationError(GL_INVALID_OPERATION, kBlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001298 return false;
1299 }
1300
Jamie Madille98b1b52018-03-08 09:47:23 -05001301 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001302 {
Geoff Langb1196682014-07-23 13:47:29 -04001303 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 }
1305
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001306 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1307 // always run it in order to avoid triggering driver bugs.
1308 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1309 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001310 {
Jamie Madille0472f32018-11-27 16:32:45 -05001311 context->validationError(GL_INVALID_VALUE, kBlitDimensionsOutOfRange);
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001312 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001313 }
1314
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001315 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1316
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001317 if (mask & GL_COLOR_BUFFER_BIT)
1318 {
Jamie Madill7f232932018-09-12 11:03:06 -04001319 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1320 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001321
He Yunchao66a41a22016-12-15 16:45:05 +08001322 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001324 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325
Geoff Langa15472a2015-08-11 11:48:03 -04001326 for (size_t drawbufferIdx = 0;
1327 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 {
Geoff Langa15472a2015-08-11 11:48:03 -04001329 const FramebufferAttachment *attachment =
1330 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1331 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001333 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334
Geoff Langb2f3d052013-08-13 12:49:27 -04001335 // The GL ES 3.0.2 spec (pg 193) states that:
1336 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001337 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1338 // as well
1339 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1340 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001341 // Changes with EXT_color_buffer_float:
1342 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001343 GLenum readComponentType = readFormat.info->componentType;
1344 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001345 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001346 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001347 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001348 drawComponentType == GL_SIGNED_NORMALIZED);
1349
1350 if (extensions.colorBufferFloat)
1351 {
1352 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1353 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1354
1355 if (readFixedOrFloat != drawFixedOrFloat)
1356 {
Jamie Madill610640f2018-11-21 17:28:41 -05001357 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001358 kBlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001359 return false;
1360 }
1361 }
1362 else if (readFixedPoint != drawFixedPoint)
1363 {
Jamie Madille0472f32018-11-27 16:32:45 -05001364 context->validationError(GL_INVALID_OPERATION, kBlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001365 return false;
1366 }
1367
1368 if (readComponentType == GL_UNSIGNED_INT &&
1369 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 {
Jamie Madill610640f2018-11-21 17:28:41 -05001371 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001372 kBlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001373 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001374 }
1375
Jamie Madill6163c752015-12-07 16:32:59 -05001376 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 {
Jamie Madill610640f2018-11-21 17:28:41 -05001378 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001379 kBlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001380 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 }
1382
Jamie Madilla3944d42016-07-22 22:13:26 -04001383 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001384 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 {
Jamie Madill610640f2018-11-21 17:28:41 -05001386 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001387 kBlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001388 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
Geoff Lange4915782017-04-12 15:19:07 -04001390
1391 if (context->getExtensions().webglCompatibility &&
1392 *readColorBuffer == *attachment)
1393 {
Jamie Madille0472f32018-11-27 16:32:45 -05001394 context->validationError(GL_INVALID_OPERATION, kBlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001395 return false;
1396 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 }
1398 }
1399
Jamie Madilla3944d42016-07-22 22:13:26 -04001400 if ((readFormat.info->componentType == GL_INT ||
1401 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1402 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 {
Jamie Madille0472f32018-11-27 16:32:45 -05001404 context->validationError(GL_INVALID_OPERATION, kBlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001405 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 }
He Yunchao66a41a22016-12-15 16:45:05 +08001408 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1409 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1410 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1411 // situation is an application error that would lead to a crash in ANGLE.
1412 else if (drawFramebuffer->hasEnabledDrawBuffer())
1413 {
Jamie Madille0472f32018-11-27 16:32:45 -05001414 context->validationError(GL_INVALID_OPERATION, kBlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001415 return false;
1416 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 }
1418
He Yunchaoced53ae2016-11-29 15:00:51 +08001419 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001420 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1421 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001423 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001425 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001426 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001427 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001428 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001429
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001430 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001431 {
Kenneth Russell69382852017-07-21 16:38:44 -04001432 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 {
Jamie Madill610640f2018-11-21 17:28:41 -05001434 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001435 kBlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001436 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001437 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001438
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001439 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001440 {
Jamie Madille0472f32018-11-27 16:32:45 -05001441 context->validationError(GL_INVALID_OPERATION, kBlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001442 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001443 }
Geoff Lange4915782017-04-12 15:19:07 -04001444
1445 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1446 {
Jamie Madille0472f32018-11-27 16:32:45 -05001447 context->validationError(GL_INVALID_OPERATION, kBlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001448 return false;
1449 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001450 }
He Yunchao66a41a22016-12-15 16:45:05 +08001451 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1452 else if (drawBuffer)
1453 {
Jamie Madille0472f32018-11-27 16:32:45 -05001454 context->validationError(GL_INVALID_OPERATION, kBlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001455 return false;
1456 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001457 }
1458 }
1459
Martin Radeva3ed4572017-07-27 18:29:37 +03001460 // ANGLE_multiview, Revision 1:
1461 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001462 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1463 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1464 // views in the current read framebuffer is more than one.
1465 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001466 {
Jamie Madille0472f32018-11-27 16:32:45 -05001467 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001468 return false;
1469 }
1470 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1471 {
Jamie Madille0472f32018-11-27 16:32:45 -05001472 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001473 return false;
1474 }
1475
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001476 return true;
1477}
1478
Jamie Madill4928b7c2017-06-20 12:57:39 -04001479bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001480 GLint x,
1481 GLint y,
1482 GLsizei width,
1483 GLsizei height,
1484 GLenum format,
1485 GLenum type,
1486 GLsizei bufSize,
1487 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001488 GLsizei *columns,
1489 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001490 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001491{
1492 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001494 return false;
1495 }
1496
Brandon Jonesd1049182018-03-28 10:02:20 -07001497 GLsizei writeLength = 0;
1498 GLsizei writeColumns = 0;
1499 GLsizei writeRows = 0;
1500
1501 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1502 &writeColumns, &writeRows, pixels))
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 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001508 {
Geoff Langb1196682014-07-23 13:47:29 -04001509 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001510 }
1511
Brandon Jonesd1049182018-03-28 10:02:20 -07001512 SetRobustLengthParam(length, writeLength);
1513 SetRobustLengthParam(columns, writeColumns);
1514 SetRobustLengthParam(rows, writeRows);
1515
Jamie Madillc29968b2016-01-20 11:17:23 -05001516 return true;
1517}
1518
1519bool ValidateReadnPixelsEXT(Context *context,
1520 GLint x,
1521 GLint y,
1522 GLsizei width,
1523 GLsizei height,
1524 GLenum format,
1525 GLenum type,
1526 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001527 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001528{
1529 if (bufSize < 0)
1530 {
Jamie Madille0472f32018-11-27 16:32:45 -05001531 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001532 return false;
1533 }
1534
Geoff Lang62fce5b2016-09-30 10:46:35 -04001535 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001536 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001537}
Jamie Madill26e91952014-03-05 15:01:27 -05001538
Jamie Madill4928b7c2017-06-20 12:57:39 -04001539bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001540 GLint x,
1541 GLint y,
1542 GLsizei width,
1543 GLsizei height,
1544 GLenum format,
1545 GLenum type,
1546 GLsizei bufSize,
1547 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001548 GLsizei *columns,
1549 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001550 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001551{
Brandon Jonesd1049182018-03-28 10:02:20 -07001552 GLsizei writeLength = 0;
1553 GLsizei writeColumns = 0;
1554 GLsizei writeRows = 0;
1555
Geoff Lang62fce5b2016-09-30 10:46:35 -04001556 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001557 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001558 return false;
1559 }
1560
Brandon Jonesd1049182018-03-28 10:02:20 -07001561 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1562 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001563 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001564 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001565 }
1566
Brandon Jonesd1049182018-03-28 10:02:20 -07001567 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001568 {
1569 return false;
1570 }
1571
Brandon Jonesd1049182018-03-28 10:02:20 -07001572 SetRobustLengthParam(length, writeLength);
1573 SetRobustLengthParam(columns, writeColumns);
1574 SetRobustLengthParam(rows, writeRows);
1575
Geoff Lang62fce5b2016-09-30 10:46:35 -04001576 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001577}
1578
Jamie Madill43da7c42018-08-01 11:34:49 -04001579bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001580{
1581 if (!context->getExtensions().occlusionQueryBoolean &&
1582 !context->getExtensions().disjointTimerQuery)
1583 {
Jamie Madille0472f32018-11-27 16:32:45 -05001584 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001585 return false;
1586 }
1587
Olli Etuaho41997e72016-03-10 13:38:39 +02001588 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001589}
1590
Jamie Madill43da7c42018-08-01 11:34:49 -04001591bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001592{
1593 if (!context->getExtensions().occlusionQueryBoolean &&
1594 !context->getExtensions().disjointTimerQuery)
1595 {
Jamie Madille0472f32018-11-27 16:32:45 -05001596 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001597 return false;
1598 }
1599
Olli Etuaho41997e72016-03-10 13:38:39 +02001600 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001601}
1602
Jamie Madill43da7c42018-08-01 11:34:49 -04001603bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001604{
1605 if (!context->getExtensions().occlusionQueryBoolean &&
1606 !context->getExtensions().disjointTimerQuery)
1607 {
Jamie Madille0472f32018-11-27 16:32:45 -05001608 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Jamie Madillf0e04492017-08-26 15:28:42 -04001609 return false;
1610 }
1611
1612 return true;
1613}
1614
Jamie Madill43da7c42018-08-01 11:34:49 -04001615bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001616{
1617 if (!ValidQueryType(context, target))
1618 {
Jamie Madille0472f32018-11-27 16:32:45 -05001619 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001620 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001621 }
1622
1623 if (id == 0)
1624 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001625 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001627 }
1628
1629 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1630 // of zero, if the active query object name for <target> is non-zero (for the
1631 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1632 // the active query for either target is non-zero), if <id> is the name of an
1633 // existing query object whose type does not match <target>, or if <id> is the
1634 // active query object name for any query type, the error INVALID_OPERATION is
1635 // generated.
1636
1637 // Ensure no other queries are active
1638 // NOTE: If other queries than occlusion are supported, we will need to check
1639 // separately that:
1640 // a) The query ID passed is not the current active query for any target/type
1641 // b) There are no active queries for the requested target (and in the case
1642 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1643 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001644
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001645 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001646 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001647 context->validationError(GL_INVALID_OPERATION, kOtherQueryActive);
Geoff Langb1196682014-07-23 13:47:29 -04001648 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001649 }
1650
1651 Query *queryObject = context->getQuery(id, true, target);
1652
1653 // check that name was obtained with glGenQueries
1654 if (!queryObject)
1655 {
Jamie Madille0472f32018-11-27 16:32:45 -05001656 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001657 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001658 }
1659
1660 // check for type mismatch
1661 if (queryObject->getType() != target)
1662 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001663 context->validationError(GL_INVALID_OPERATION, kQueryTargetMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001664 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001665 }
1666
1667 return true;
1668}
1669
Jamie Madill43da7c42018-08-01 11:34:49 -04001670bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671{
1672 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001673 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001674 {
Jamie Madille0472f32018-11-27 16:32:45 -05001675 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001676 return false;
1677 }
1678
1679 return ValidateBeginQueryBase(context, target, id);
1680}
1681
Jamie Madill43da7c42018-08-01 11:34:49 -04001682bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001683{
1684 if (!ValidQueryType(context, target))
1685 {
Jamie Madille0472f32018-11-27 16:32:45 -05001686 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001687 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001688 }
1689
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001690 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001691
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001692 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001693 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001694 context->validationError(GL_INVALID_OPERATION, kQueryInactive);
Geoff Langb1196682014-07-23 13:47:29 -04001695 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001696 }
1697
Jamie Madill45c785d2014-05-13 14:09:34 -04001698 return true;
1699}
1700
Jamie Madill43da7c42018-08-01 11:34:49 -04001701bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702{
1703 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001704 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 {
Jamie Madille0472f32018-11-27 16:32:45 -05001706 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001707 return false;
1708 }
1709
1710 return ValidateEndQueryBase(context, target);
1711}
1712
Corentin Wallezad3ae902018-03-09 13:40:42 -05001713bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001714{
1715 if (!context->getExtensions().disjointTimerQuery)
1716 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001717 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001718 return false;
1719 }
1720
Corentin Wallezad3ae902018-03-09 13:40:42 -05001721 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 {
Jamie Madille0472f32018-11-27 16:32:45 -05001723 context->validationError(GL_INVALID_ENUM, kInvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001724 return false;
1725 }
1726
1727 Query *queryObject = context->getQuery(id, true, target);
1728 if (queryObject == nullptr)
1729 {
Jamie Madille0472f32018-11-27 16:32:45 -05001730 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 return false;
1732 }
1733
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001734 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001735 {
Jamie Madille0472f32018-11-27 16:32:45 -05001736 context->validationError(GL_INVALID_OPERATION, kQueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 return false;
1738 }
1739
1740 return true;
1741}
1742
Corentin Wallezad3ae902018-03-09 13:40:42 -05001743bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744{
Geoff Lang2186c382016-10-14 10:54:54 -04001745 if (numParams)
1746 {
1747 *numParams = 0;
1748 }
1749
Corentin Wallezad3ae902018-03-09 13:40:42 -05001750 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001751 {
Jamie Madille0472f32018-11-27 16:32:45 -05001752 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 return false;
1754 }
1755
1756 switch (pname)
1757 {
1758 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001759 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001760 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001761 context->validationError(GL_INVALID_ENUM, kInvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001762 return false;
1763 }
1764 break;
1765 case GL_QUERY_COUNTER_BITS_EXT:
1766 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001767 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001768 {
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 break;
1773 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001774 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001775 return false;
1776 }
1777
Geoff Lang2186c382016-10-14 10:54:54 -04001778 if (numParams)
1779 {
1780 // All queries return only one value
1781 *numParams = 1;
1782 }
1783
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001784 return true;
1785}
1786
Corentin Wallezad3ae902018-03-09 13:40:42 -05001787bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788{
1789 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001790 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001791 {
Jamie Madille0472f32018-11-27 16:32:45 -05001792 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001793 return false;
1794 }
1795
Geoff Lang2186c382016-10-14 10:54:54 -04001796 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001797}
1798
Geoff Lang2186c382016-10-14 10:54:54 -04001799bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001800 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001801 GLenum pname,
1802 GLsizei bufSize,
1803 GLsizei *length,
1804 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001805{
Geoff Lang2186c382016-10-14 10:54:54 -04001806 if (!ValidateRobustEntryPoint(context, bufSize))
1807 {
1808 return false;
1809 }
1810
Brandon Jonesd1049182018-03-28 10:02:20 -07001811 GLsizei numParams = 0;
1812
1813 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001814 {
1815 return false;
1816 }
1817
Brandon Jonesd1049182018-03-28 10:02:20 -07001818 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001819 {
1820 return false;
1821 }
1822
Brandon Jonesd1049182018-03-28 10:02:20 -07001823 SetRobustLengthParam(length, numParams);
1824
Geoff Lang2186c382016-10-14 10:54:54 -04001825 return true;
1826}
1827
1828bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1829{
1830 if (numParams)
1831 {
1832 *numParams = 0;
1833 }
1834
Corentin Wallezad3ae902018-03-09 13:40:42 -05001835 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001836
1837 if (!queryObject)
1838 {
Jamie Madille0472f32018-11-27 16:32:45 -05001839 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001840 return false;
1841 }
1842
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001843 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001844 {
Jamie Madille0472f32018-11-27 16:32:45 -05001845 context->validationError(GL_INVALID_OPERATION, kQueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001846 return false;
1847 }
1848
1849 switch (pname)
1850 {
1851 case GL_QUERY_RESULT_EXT:
1852 case GL_QUERY_RESULT_AVAILABLE_EXT:
1853 break;
1854
1855 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001856 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001857 return false;
1858 }
1859
Geoff Lang2186c382016-10-14 10:54:54 -04001860 if (numParams)
1861 {
1862 *numParams = 1;
1863 }
1864
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865 return true;
1866}
1867
1868bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1869{
1870 if (!context->getExtensions().disjointTimerQuery)
1871 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001872 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873 return false;
1874 }
Geoff Lang2186c382016-10-14 10:54:54 -04001875 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1876}
1877
1878bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1879 GLuint id,
1880 GLenum pname,
1881 GLsizei bufSize,
1882 GLsizei *length,
1883 GLint *params)
1884{
1885 if (!context->getExtensions().disjointTimerQuery)
1886 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001887 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001888 return false;
1889 }
1890
1891 if (!ValidateRobustEntryPoint(context, bufSize))
1892 {
1893 return false;
1894 }
1895
Brandon Jonesd1049182018-03-28 10:02:20 -07001896 GLsizei numParams = 0;
1897
1898 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001899 {
1900 return false;
1901 }
1902
Brandon Jonesd1049182018-03-28 10:02:20 -07001903 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001904 {
1905 return false;
1906 }
1907
Brandon Jonesd1049182018-03-28 10:02:20 -07001908 SetRobustLengthParam(length, numParams);
1909
Geoff Lang2186c382016-10-14 10:54:54 -04001910 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001911}
1912
1913bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1914{
1915 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001916 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001917 {
Jamie Madille0472f32018-11-27 16:32:45 -05001918 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919 return false;
1920 }
Geoff Lang2186c382016-10-14 10:54:54 -04001921 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1922}
1923
1924bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1925 GLuint id,
1926 GLenum pname,
1927 GLsizei bufSize,
1928 GLsizei *length,
1929 GLuint *params)
1930{
1931 if (!context->getExtensions().disjointTimerQuery &&
1932 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1933 {
Jamie Madille0472f32018-11-27 16:32:45 -05001934 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001935 return false;
1936 }
1937
1938 if (!ValidateRobustEntryPoint(context, bufSize))
1939 {
1940 return false;
1941 }
1942
Brandon Jonesd1049182018-03-28 10:02:20 -07001943 GLsizei numParams = 0;
1944
1945 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001946 {
1947 return false;
1948 }
1949
Brandon Jonesd1049182018-03-28 10:02:20 -07001950 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001951 {
1952 return false;
1953 }
1954
Brandon Jonesd1049182018-03-28 10:02:20 -07001955 SetRobustLengthParam(length, numParams);
1956
Geoff Lang2186c382016-10-14 10:54:54 -04001957 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001958}
1959
1960bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1961{
1962 if (!context->getExtensions().disjointTimerQuery)
1963 {
Jamie Madille0472f32018-11-27 16:32:45 -05001964 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001965 return false;
1966 }
Geoff Lang2186c382016-10-14 10:54:54 -04001967 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1968}
1969
1970bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1971 GLuint id,
1972 GLenum pname,
1973 GLsizei bufSize,
1974 GLsizei *length,
1975 GLint64 *params)
1976{
1977 if (!context->getExtensions().disjointTimerQuery)
1978 {
Jamie Madille0472f32018-11-27 16:32:45 -05001979 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001980 return false;
1981 }
1982
1983 if (!ValidateRobustEntryPoint(context, bufSize))
1984 {
1985 return false;
1986 }
1987
Brandon Jonesd1049182018-03-28 10:02:20 -07001988 GLsizei numParams = 0;
1989
1990 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001991 {
1992 return false;
1993 }
1994
Brandon Jonesd1049182018-03-28 10:02:20 -07001995 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001996 {
1997 return false;
1998 }
1999
Brandon Jonesd1049182018-03-28 10:02:20 -07002000 SetRobustLengthParam(length, numParams);
2001
Geoff Lang2186c382016-10-14 10:54:54 -04002002 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002003}
2004
2005bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2006{
2007 if (!context->getExtensions().disjointTimerQuery)
2008 {
Jamie Madille0472f32018-11-27 16:32:45 -05002009 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010 return false;
2011 }
Geoff Lang2186c382016-10-14 10:54:54 -04002012 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2013}
2014
2015bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2016 GLuint id,
2017 GLenum pname,
2018 GLsizei bufSize,
2019 GLsizei *length,
2020 GLuint64 *params)
2021{
2022 if (!context->getExtensions().disjointTimerQuery)
2023 {
Jamie Madille0472f32018-11-27 16:32:45 -05002024 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002025 return false;
2026 }
2027
2028 if (!ValidateRobustEntryPoint(context, bufSize))
2029 {
2030 return false;
2031 }
2032
Brandon Jonesd1049182018-03-28 10:02:20 -07002033 GLsizei numParams = 0;
2034
2035 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002036 {
2037 return false;
2038 }
2039
Brandon Jonesd1049182018-03-28 10:02:20 -07002040 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002041 {
2042 return false;
2043 }
2044
Brandon Jonesd1049182018-03-28 10:02:20 -07002045 SetRobustLengthParam(length, numParams);
2046
Geoff Lang2186c382016-10-14 10:54:54 -04002047 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002048}
2049
Jamie Madill5b772312018-03-08 20:28:32 -05002050bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002051 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002052 GLint location,
2053 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002054 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002055{
Jiajia Qin5451d532017-11-16 17:16:34 +08002056 // TODO(Jiajia): Add image uniform check in future.
2057 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002058 {
Jamie Madille0472f32018-11-27 16:32:45 -05002059 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002060 return false;
2061 }
2062
Jiajia Qin5451d532017-11-16 17:16:34 +08002063 if (!program)
2064 {
Jamie Madille0472f32018-11-27 16:32:45 -05002065 context->validationError(GL_INVALID_OPERATION, kInvalidProgramName);
Jiajia Qin5451d532017-11-16 17:16:34 +08002066 return false;
2067 }
2068
2069 if (!program->isLinked())
2070 {
Jamie Madille0472f32018-11-27 16:32:45 -05002071 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiajia Qin5451d532017-11-16 17:16:34 +08002072 return false;
2073 }
2074
2075 if (location == -1)
2076 {
2077 // Silently ignore the uniform command
2078 return false;
2079 }
2080
2081 const auto &uniformLocations = program->getUniformLocations();
2082 size_t castedLocation = static_cast<size_t>(location);
2083 if (castedLocation >= uniformLocations.size())
2084 {
Jamie Madille0472f32018-11-27 16:32:45 -05002085 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
Jiajia Qin5451d532017-11-16 17:16:34 +08002086 return false;
2087 }
2088
2089 const auto &uniformLocation = uniformLocations[castedLocation];
2090 if (uniformLocation.ignored)
2091 {
2092 // Silently ignore the uniform command
2093 return false;
2094 }
2095
2096 if (!uniformLocation.used())
2097 {
Jamie Madille0472f32018-11-27 16:32:45 -05002098 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
Jiajia Qin5451d532017-11-16 17:16:34 +08002099 return false;
2100 }
2101
2102 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2103
2104 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002105 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002106 {
Jamie Madille0472f32018-11-27 16:32:45 -05002107 context->validationError(GL_INVALID_OPERATION, kInvalidUniformCount);
Jiajia Qin5451d532017-11-16 17:16:34 +08002108 return false;
2109 }
2110
2111 *uniformOut = &uniform;
2112 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002113}
2114
Jamie Madill5b772312018-03-08 20:28:32 -05002115bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002116 GLenum uniformType,
2117 GLsizei count,
2118 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002119{
Jiajia Qin5451d532017-11-16 17:16:34 +08002120 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2121 // It is compatible with INT or BOOL.
2122 // Do these cheap tests first, for a little extra speed.
2123 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002124 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002125 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002126 }
2127
Jiajia Qin5451d532017-11-16 17:16:34 +08002128 if (IsSamplerType(uniformType))
2129 {
2130 // Check that the values are in range.
2131 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2132 for (GLsizei i = 0; i < count; ++i)
2133 {
2134 if (value[i] < 0 || value[i] >= max)
2135 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002136 context->validationError(GL_INVALID_VALUE, kSamplerUniformValueOutOfRange);
Jiajia Qin5451d532017-11-16 17:16:34 +08002137 return false;
2138 }
2139 }
2140 return true;
2141 }
2142
Jamie Madillc3e37312018-11-30 15:25:39 -05002143 context->validationError(GL_INVALID_OPERATION, kUniformTypeMismatch);
Jiajia Qin5451d532017-11-16 17:16:34 +08002144 return false;
2145}
2146
Jamie Madill5b772312018-03-08 20:28:32 -05002147bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002148{
2149 // Check that the value type is compatible with uniform type.
2150 if (valueType == uniformType)
2151 {
2152 return true;
2153 }
2154
Jamie Madillc3e37312018-11-30 15:25:39 -05002155 context->validationError(GL_INVALID_OPERATION, kUniformTypeMismatch);
Jiajia Qin5451d532017-11-16 17:16:34 +08002156 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002157}
2158
Jamie Madill5b772312018-03-08 20:28:32 -05002159bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002160{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002161 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002162 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002163 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2164 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002165}
2166
Jamie Madill5b772312018-03-08 20:28:32 -05002167bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002168{
2169 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002170 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmana98a6472017-02-02 21:38:32 -05002171 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2172 ValidateUniform1ivValue(context, uniform->type, count, value);
2173}
2174
Jamie Madill5b772312018-03-08 20:28:32 -05002175bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002176 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002177 GLint location,
2178 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002179 GLboolean transpose)
2180{
Geoff Lang92019432017-11-20 13:09:34 -05002181 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002182 {
Jamie Madille0472f32018-11-27 16:32:45 -05002183 context->validationError(GL_INVALID_VALUE, kES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04002184 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002185 }
2186
Jamie Madill62d31cb2015-09-11 13:25:51 -04002187 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002188 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002189 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2190 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002191}
2192
Jamie Madill5b772312018-03-08 20:28:32 -05002193bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002194{
2195 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2196 {
Jamie Madille0472f32018-11-27 16:32:45 -05002197 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Geoff Langb1196682014-07-23 13:47:29 -04002198 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002199 }
2200
Jamie Madill0af26e12015-03-05 19:54:33 -05002201 const Caps &caps = context->getCaps();
2202
Jamie Madill893ab082014-05-16 16:56:10 -04002203 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2204 {
2205 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2206
Jamie Madill0af26e12015-03-05 19:54:33 -05002207 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002208 {
Jamie Madille0472f32018-11-27 16:32:45 -05002209 context->validationError(GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer);
Geoff Langb1196682014-07-23 13:47:29 -04002210 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002211 }
2212 }
2213
2214 switch (pname)
2215 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002216 case GL_TEXTURE_BINDING_2D:
2217 case GL_TEXTURE_BINDING_CUBE_MAP:
2218 case GL_TEXTURE_BINDING_3D:
2219 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002220 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002221 break;
Olli Etuahod310a432018-08-24 15:40:23 +03002222 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
Olli Etuaho064458a2018-08-30 14:02:02 +03002223 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03002224 {
Jamie Madille0472f32018-11-27 16:32:45 -05002225 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
Olli Etuahod310a432018-08-24 15:40:23 +03002226 return false;
2227 }
2228 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002229 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2230 if (!context->getExtensions().textureRectangle)
2231 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002232 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002233 return false;
2234 }
2235 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002236 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2237 if (!context->getExtensions().eglStreamConsumerExternal &&
2238 !context->getExtensions().eglImageExternal)
2239 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002240 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08002241 return false;
2242 }
2243 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002244
He Yunchaoced53ae2016-11-29 15:00:51 +08002245 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2246 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002247 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002248 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2249 ASSERT(readFramebuffer);
2250
Jamie Madill610640f2018-11-21 17:28:41 -05002251 if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002252 {
Geoff Langb1196682014-07-23 13:47:29 -04002253 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002254 }
2255
Jamie Madille98b1b52018-03-08 09:47:23 -05002256 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002257 {
Jamie Madille0472f32018-11-27 16:32:45 -05002258 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002259 return false;
2260 }
2261
Jamie Madille98b1b52018-03-08 09:47:23 -05002262 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002263 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002264 {
Jamie Madille0472f32018-11-27 16:32:45 -05002265 context->validationError(GL_INVALID_OPERATION, kReadBufferNotAttached);
Geoff Langb1196682014-07-23 13:47:29 -04002266 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002267 }
2268 }
2269 break;
2270
He Yunchaoced53ae2016-11-29 15:00:51 +08002271 default:
2272 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002273 }
2274
2275 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002276 if (*numParams == 0)
2277 {
2278 return false;
2279 }
2280
2281 return true;
2282}
2283
Brandon Jonesd1049182018-03-28 10:02:20 -07002284bool ValidateGetBooleanvRobustANGLE(Context *context,
2285 GLenum pname,
2286 GLsizei bufSize,
2287 GLsizei *length,
2288 GLboolean *params)
2289{
2290 GLenum nativeType;
2291 unsigned int numParams = 0;
2292
2293 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2294 {
2295 return false;
2296 }
2297
2298 SetRobustLengthParam(length, numParams);
2299
2300 return true;
2301}
2302
2303bool ValidateGetFloatvRobustANGLE(Context *context,
2304 GLenum pname,
2305 GLsizei bufSize,
2306 GLsizei *length,
2307 GLfloat *params)
2308{
2309 GLenum nativeType;
2310 unsigned int numParams = 0;
2311
2312 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2313 {
2314 return false;
2315 }
2316
2317 SetRobustLengthParam(length, numParams);
2318
2319 return true;
2320}
2321
2322bool ValidateGetIntegervRobustANGLE(Context *context,
2323 GLenum pname,
2324 GLsizei bufSize,
2325 GLsizei *length,
2326 GLint *data)
2327{
2328 GLenum nativeType;
2329 unsigned int numParams = 0;
2330
2331 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2332 {
2333 return false;
2334 }
2335
2336 SetRobustLengthParam(length, numParams);
2337
2338 return true;
2339}
2340
2341bool ValidateGetInteger64vRobustANGLE(Context *context,
2342 GLenum pname,
2343 GLsizei bufSize,
2344 GLsizei *length,
2345 GLint64 *data)
2346{
2347 GLenum nativeType;
2348 unsigned int numParams = 0;
2349
2350 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2351 {
2352 return false;
2353 }
2354
2355 if (nativeType == GL_INT_64_ANGLEX)
2356 {
2357 CastStateValues(context, nativeType, pname, numParams, data);
2358 return false;
2359 }
2360
2361 SetRobustLengthParam(length, numParams);
2362 return true;
2363}
2364
Jamie Madill5b772312018-03-08 20:28:32 -05002365bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002366 GLenum pname,
2367 GLsizei bufSize,
2368 GLenum *nativeType,
2369 unsigned int *numParams)
2370{
2371 if (!ValidateRobustEntryPoint(context, bufSize))
2372 {
2373 return false;
2374 }
2375
2376 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2377 {
2378 return false;
2379 }
2380
2381 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002382 {
2383 return false;
2384 }
2385
2386 return true;
2387}
2388
Jamie Madill5b772312018-03-08 20:28:32 -05002389bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002390 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002391 GLint level,
2392 GLenum internalformat,
2393 bool isSubImage,
2394 GLint xoffset,
2395 GLint yoffset,
2396 GLint zoffset,
2397 GLint x,
2398 GLint y,
2399 GLsizei width,
2400 GLsizei height,
2401 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002402 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002403{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002404 TextureType texType = TextureTargetToType(target);
2405
Brandon Jones6cad5662017-06-14 13:25:13 -07002406 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002407 {
Jamie Madille0472f32018-11-27 16:32:45 -05002408 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07002409 return false;
2410 }
2411
2412 if (width < 0 || height < 0)
2413 {
Jamie Madille0472f32018-11-27 16:32:45 -05002414 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002415 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002416 }
2417
He Yunchaoced53ae2016-11-29 15:00:51 +08002418 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2419 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002420 {
Jamie Madille0472f32018-11-27 16:32:45 -05002421 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
Geoff Langb1196682014-07-23 13:47:29 -04002422 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002423 }
2424
2425 if (border != 0)
2426 {
Jamie Madille0472f32018-11-27 16:32:45 -05002427 context->validationError(GL_INVALID_VALUE, kInvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002428 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002429 }
2430
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002431 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002432 {
Jamie Madille0472f32018-11-27 16:32:45 -05002433 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002434 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002435 }
2436
Jamie Madill43da7c42018-08-01 11:34:49 -04002437 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002438 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002439 if (!ValidateFramebufferComplete(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
Jamie Madille98b1b52018-03-08 09:47:23 -05002444 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002445 {
Geoff Langb1196682014-07-23 13:47:29 -04002446 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002447 }
2448
Martin Radev138064f2016-07-15 12:03:41 +03002449 if (readFramebuffer->getReadBufferState() == GL_NONE)
2450 {
Jamie Madille0472f32018-11-27 16:32:45 -05002451 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002452 return false;
2453 }
2454
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002455 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2456 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002457 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002458 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002459 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2460 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002461 {
Jamie Madille0472f32018-11-27 16:32:45 -05002462 context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002463 return false;
2464 }
2465
Martin Radev04e2c3b2017-07-27 16:54:35 +03002466 // ANGLE_multiview spec, Revision 1:
2467 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2468 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002469 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2470 // framebuffer is more than one.
2471 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002472 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002473 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
Martin Radev04e2c3b2017-07-27 16:54:35 +03002474 return false;
2475 }
2476
Jamie Madill43da7c42018-08-01 11:34:49 -04002477 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002478
Geoff Langaae65a42014-05-26 12:43:44 -04002479 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002480 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002481 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002482 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002483 maxDimension = caps.max2DTextureSize;
2484 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002485
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002486 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002487 maxDimension = caps.maxCubeMapTextureSize;
2488 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002489
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002490 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002491 maxDimension = caps.maxRectangleTextureSize;
2492 break;
2493
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002494 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002495 maxDimension = caps.max2DTextureSize;
2496 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002497
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002498 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002499 maxDimension = caps.max3DTextureSize;
2500 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002501
He Yunchaoced53ae2016-11-29 15:00:51 +08002502 default:
Jamie Madille0472f32018-11-27 16:32:45 -05002503 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08002504 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002505 }
2506
Jamie Madill43da7c42018-08-01 11:34:49 -04002507 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002508 if (!texture)
2509 {
Jamie Madille0472f32018-11-27 16:32:45 -05002510 context->validationError(GL_INVALID_OPERATION, kTextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002511 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002512 }
2513
Geoff Lang69cce582015-09-17 13:20:36 -04002514 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002515 {
Jamie Madille0472f32018-11-27 16:32:45 -05002516 context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
Geoff Langb1196682014-07-23 13:47:29 -04002517 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002518 }
2519
Jamie Madill43da7c42018-08-01 11:34:49 -04002520 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002521 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002522 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002523
Geoff Lang966c9402017-04-18 12:38:27 -04002524 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002525 {
Jamie Madille0472f32018-11-27 16:32:45 -05002526 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
Geoff Langa9be0dc2014-12-17 12:34:40 -05002527 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002528 }
2529
2530 if (isSubImage)
2531 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002532 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2533 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2534 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002535 {
Jamie Madille0472f32018-11-27 16:32:45 -05002536 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
Geoff Langb1196682014-07-23 13:47:29 -04002537 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002538 }
2539 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002540 else
2541 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002542 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002543 {
Jamie Madille0472f32018-11-27 16:32:45 -05002544 context->validationError(GL_INVALID_VALUE, kCubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002545 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002546 }
2547
Geoff Langeb66a6e2016-10-31 13:06:12 -04002548 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002549 {
Jamie Madille0472f32018-11-27 16:32:45 -05002550 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002551 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002552 }
2553
2554 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002555 if (static_cast<int>(width) > maxLevelDimension ||
2556 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002557 {
Jamie Madille0472f32018-11-27 16:32:45 -05002558 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002559 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002560 }
2561 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002562
Jamie Madill0c8abca2016-07-22 20:21:26 -04002563 if (textureFormatOut)
2564 {
2565 *textureFormatOut = texture->getFormat(target, level);
2566 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002567
2568 // Detect texture copying feedback loops for WebGL.
2569 if (context->getExtensions().webglCompatibility)
2570 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002571 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002572 {
Jamie Madille0472f32018-11-27 16:32:45 -05002573 context->validationError(GL_INVALID_OPERATION, kFeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002574 return false;
2575 }
2576 }
2577
Jamie Madill560a8d82014-05-21 13:06:20 -04002578 return true;
2579}
2580
Jamie Madillb42162f2018-08-20 12:58:37 -04002581// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2582// completeness check.
2583const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002584{
2585 const Extensions &extensions = context->getExtensions();
Jamie Madill7f232932018-09-12 11:03:06 -04002586 const State &state = context->getGLState();
Jamie Madille7d80f32018-08-08 15:49:23 -04002587
2588 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2589 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2590 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madilld84b6732018-09-06 15:54:35 -04002591 VertexArray *vertexArray = state.getVertexArray();
2592 ASSERT(vertexArray);
2593
2594 if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
Jamie Madille7d80f32018-08-08 15:49:23 -04002595 {
Jamie Madille0472f32018-11-27 16:32:45 -05002596 return kBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002597 }
2598
2599 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2600 // Section 6.10 of the WebGL 1.0 spec.
2601 Framebuffer *framebuffer = state.getDrawFramebuffer();
Jamie Madilld84b6732018-09-06 15:54:35 -04002602 ASSERT(framebuffer);
2603
Jamie Madille7d80f32018-08-08 15:49:23 -04002604 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2605 {
2606 ASSERT(framebuffer);
2607 const FramebufferAttachment *dsAttachment =
2608 framebuffer->getStencilOrDepthStencilAttachment();
2609 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2610 ASSERT(stencilBits <= 8);
2611
2612 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2613 if (depthStencilState.stencilTest && stencilBits > 0)
2614 {
2615 GLuint maxStencilValue = (1 << stencilBits) - 1;
2616
2617 bool differentRefs =
2618 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2619 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2620 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2621 (depthStencilState.stencilBackWritemask & maxStencilValue);
2622 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2623 (depthStencilState.stencilBackMask & maxStencilValue);
2624
2625 if (differentRefs || differentWritemasks || differentMasks)
2626 {
2627 if (!extensions.webglCompatibility)
2628 {
2629 WARN() << "This ANGLE implementation does not support separate front/back "
2630 "stencil writemasks, reference values, or stencil mask values.";
2631 }
Jamie Madille0472f32018-11-27 16:32:45 -05002632 return kStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002633 }
2634 }
2635 }
2636
2637 if (!framebuffer->isComplete(context))
2638 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002639 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
Jamie Madille0472f32018-11-27 16:32:45 -05002640 return kDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002641 }
2642
2643 if (context->getStateCache().hasAnyEnabledClientAttrib())
2644 {
2645 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2646 {
2647 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2648 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2649 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2650 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madille0472f32018-11-27 16:32:45 -05002651 return kVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002652 }
2653
2654 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2655 {
2656 // This is an application error that would normally result in a crash, but we catch it
2657 // and return an error
Jamie Madille0472f32018-11-27 16:32:45 -05002658 return kVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002659 }
2660 }
2661
2662 // If we are running GLES1, there is no current program.
2663 if (context->getClientVersion() >= Version(2, 0))
2664 {
Jamie Madill785e8a02018-10-04 17:42:00 -04002665 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002666 if (!program)
2667 {
Jamie Madille0472f32018-11-27 16:32:45 -05002668 return kProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002669 }
2670
2671 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2672 // vertex shader stage or fragment shader stage is a undefined behaviour.
2673 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2674 // produce undefined result.
2675 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2676 !program->hasLinkedShaderStage(ShaderType::Fragment))
2677 {
Jamie Madille0472f32018-11-27 16:32:45 -05002678 return kNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002679 }
2680
2681 if (!program->validateSamplers(nullptr, context->getCaps()))
2682 {
Jamie Madille0472f32018-11-27 16:32:45 -05002683 return kTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002684 }
2685
2686 if (extensions.multiview)
2687 {
2688 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2689 const int framebufferNumViews = framebuffer->getNumViews();
2690 if (framebufferNumViews != programNumViews)
2691 {
Jamie Madille0472f32018-11-27 16:32:45 -05002692 return kMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002693 }
2694
2695 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2696 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
Jamie Madill3a256222018-12-08 09:56:39 -05002697 !transformFeedbackObject->isPaused() && framebufferNumViews > 1)
Jamie Madille7d80f32018-08-08 15:49:23 -04002698 {
Jamie Madille0472f32018-11-27 16:32:45 -05002699 return kMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002700 }
2701
2702 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2703 state.isQueryActive(QueryType::TimeElapsed))
2704 {
Jamie Madille0472f32018-11-27 16:32:45 -05002705 return kMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002706 }
2707 }
2708
2709 // Uniform buffer validation
2710 for (unsigned int uniformBlockIndex = 0;
2711 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2712 {
2713 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Jamie Madill7f232932018-09-12 11:03:06 -04002714 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Jamie Madille7d80f32018-08-08 15:49:23 -04002715 const OffsetBindingPointer<Buffer> &uniformBuffer =
2716 state.getIndexedUniformBuffer(blockBinding);
2717
2718 if (uniformBuffer.get() == nullptr)
2719 {
2720 // undefined behaviour
Jamie Madille0472f32018-11-27 16:32:45 -05002721 return kUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002722 }
2723
2724 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2725 if (uniformBufferSize < uniformBlock.dataSize)
2726 {
2727 // undefined behaviour
Jamie Madille0472f32018-11-27 16:32:45 -05002728 return kUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002729 }
2730
2731 if (extensions.webglCompatibility &&
2732 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2733 {
Jamie Madille0472f32018-11-27 16:32:45 -05002734 return kUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002735 }
2736 }
2737
2738 // Do some additonal WebGL-specific validation
2739 if (extensions.webglCompatibility)
2740 {
2741 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2742 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2743 transformFeedbackObject->buffersBoundForOtherUse())
2744 {
Jamie Madille0472f32018-11-27 16:32:45 -05002745 return kTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002746 }
2747
2748 // Detect rendering feedback loops for WebGL.
2749 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2750 {
Jamie Madille0472f32018-11-27 16:32:45 -05002751 return kFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002752 }
2753
2754 // Detect that the vertex shader input types match the attribute types
2755 if (!ValidateVertexShaderAttributeTypeMatch(context))
2756 {
Jamie Madille0472f32018-11-27 16:32:45 -05002757 return kVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002758 }
2759
2760 // Detect that the color buffer types match the fragment shader output types
2761 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2762 {
Jamie Madille0472f32018-11-27 16:32:45 -05002763 return kDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002764 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002765
2766 const VertexArray *vao = context->getGLState().getVertexArray();
2767 if (vao->hasTransformFeedbackBindingConflict(context))
2768 {
Jamie Madille0472f32018-11-27 16:32:45 -05002769 return kVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002770 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002771 }
2772 }
2773
Jamie Madillb42162f2018-08-20 12:58:37 -04002774 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002775}
2776
Jamie Madill16e28fd2018-09-12 11:03:05 -04002777bool ValidateDrawMode(Context *context, PrimitiveMode mode)
Jamie Madill250d33f2014-06-06 17:09:03 -04002778{
Jamie Madill9b025062018-12-12 15:44:12 -05002779 const State &state = context->getGLState();
2780 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
2781 if (curTransformFeedback && curTransformFeedback->isActive() &&
2782 !curTransformFeedback->isPaused())
2783 {
2784 if (!ValidateTransformFeedbackPrimitiveMode(context,
2785 curTransformFeedback->getPrimitiveMode(), mode))
2786 {
2787 context->validationError(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
2788 return false;
2789 }
2790 }
2791
Jiawei Shaofccebff2018-03-08 13:51:02 +08002792 const Extensions &extensions = context->getExtensions();
2793
Jamie Madill1aeb1312014-06-20 13:21:25 -04002794 switch (mode)
2795 {
Jamie Madill493f9572018-05-24 19:52:15 -04002796 case PrimitiveMode::Points:
2797 case PrimitiveMode::Lines:
2798 case PrimitiveMode::LineLoop:
2799 case PrimitiveMode::LineStrip:
2800 case PrimitiveMode::Triangles:
2801 case PrimitiveMode::TriangleStrip:
2802 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002803 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002804
Jamie Madill493f9572018-05-24 19:52:15 -04002805 case PrimitiveMode::LinesAdjacency:
2806 case PrimitiveMode::LineStripAdjacency:
2807 case PrimitiveMode::TrianglesAdjacency:
2808 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002809 if (!extensions.geometryShader)
2810 {
Jamie Madille0472f32018-11-27 16:32:45 -05002811 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shaofccebff2018-03-08 13:51:02 +08002812 return false;
2813 }
2814 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002815 default:
Jamie Madille0472f32018-11-27 16:32:45 -05002816 context->validationError(GL_INVALID_ENUM, kInvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002817 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002818 }
2819
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002820 // If we are running GLES1, there is no current program.
2821 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002822 {
Jamie Madill785e8a02018-10-04 17:42:00 -04002823 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002824 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002825
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002826 // Do geometry shader specific validations
2827 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002828 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002829 if (!IsCompatibleDrawModeWithGeometryShader(
2830 mode, program->getGeometryShaderInputPrimitiveType()))
2831 {
Jamie Madill610640f2018-11-21 17:28:41 -05002832 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05002833 kIncompatibleDrawModeAgainstGeometryShader);
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002834 return false;
2835 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002836 }
2837 }
2838
Jamie Madill9fdaa492018-02-16 10:52:11 -05002839 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002840}
2841
Jamie Madill5b772312018-03-08 20:28:32 -05002842bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002843 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002844 GLint first,
2845 GLsizei count,
2846 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002847{
Jamie Madillfd716582014-06-06 17:09:04 -04002848 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002849 {
Jamie Madille0472f32018-11-27 16:32:45 -05002850 context->validationError(GL_INVALID_VALUE, kNegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002851 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002852 }
2853
Jamie Madillf5c88e72018-12-08 09:56:38 -05002854 if (!ValidateDrawBase(context, mode, count))
Jamie Madill16e28fd2018-09-12 11:03:05 -04002855 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002856 return false;
2857 }
2858
Jamie Madill7f232932018-09-12 11:03:06 -04002859 const State &state = context->getGLState();
2860 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002861 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002862 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002863 {
James Darpinian30b604d2018-03-12 17:26:57 -07002864 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2865 {
Jamie Madille0472f32018-11-27 16:32:45 -05002866 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackBufferTooSmall);
James Darpinian30b604d2018-03-12 17:26:57 -07002867 return false;
2868 }
Jamie Madillfd716582014-06-06 17:09:04 -04002869 }
2870
Corentin Wallez71168a02016-12-19 15:11:18 -08002871 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002872 // - first < 0 has been checked as an error condition.
2873 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002874 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002875 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002876 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002877 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002878 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2879 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2880 {
Jamie Madille0472f32018-11-27 16:32:45 -05002881 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madill9fdaa492018-02-16 10:52:11 -05002882 return false;
2883 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002884
Jamie Madill2da53562018-08-01 11:34:47 -04002885 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002886 {
2887 return false;
2888 }
Jamie Madillfd716582014-06-06 17:09:04 -04002889 }
2890
2891 return true;
2892}
2893
He Yunchaoced53ae2016-11-29 15:00:51 +08002894bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002895 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002896 GLint first,
2897 GLsizei count,
2898 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002899{
Geoff Lang63c5a592017-09-27 14:08:16 -04002900 if (!context->getExtensions().instancedArrays)
2901 {
Jamie Madille0472f32018-11-27 16:32:45 -05002902 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang63c5a592017-09-27 14:08:16 -04002903 return false;
2904 }
2905
Corentin Wallez170efbf2017-05-02 13:45:01 -04002906 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002907 {
2908 return false;
2909 }
2910
Corentin Wallez0dc97812017-06-22 14:38:44 -04002911 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002912}
2913
Jamie Madill8dc27f92018-11-29 11:45:44 -05002914bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, DrawElementsType type)
Jamie Madillfd716582014-06-06 17:09:04 -04002915{
Jamie Madill8dc27f92018-11-29 11:45:44 -05002916 if (!context->getStateCache().isValidDrawElementsType(type))
Jamie Madill250d33f2014-06-06 17:09:03 -04002917 {
Jamie Madill8dc27f92018-11-29 11:45:44 -05002918 if (type == DrawElementsType::UnsignedInt)
2919 {
Jamie Madille0472f32018-11-27 16:32:45 -05002920 context->validationError(GL_INVALID_ENUM, kTypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002921 return false;
Jamie Madill8dc27f92018-11-29 11:45:44 -05002922 }
2923
2924 ASSERT(type == DrawElementsType::InvalidEnum);
2925 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2926 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002927 }
2928
Jamie Madill1e853262018-12-21 09:07:38 -05002929 intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context);
2930 if (drawElementsError)
2931 {
2932 // All errors from ValidateDrawElementsStates return INVALID_OPERATION.
2933 const char *errorMessage = reinterpret_cast<const char *>(drawElementsError);
2934 context->validationError(GL_INVALID_OPERATION, errorMessage);
2935 return false;
2936 }
2937
2938 // Note that we are missing overflow checks for active transform feedback buffers.
2939 return true;
2940}
2941
2942const char *ValidateDrawElementsStates(Context *context)
2943{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002944 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002945
Jamie Madill43da7c42018-08-01 11:34:49 -04002946 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002947 if (curTransformFeedback && curTransformFeedback->isActive() &&
2948 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002949 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002950 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2951 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
Jamie Madill9b025062018-12-12 15:44:12 -05002952 if (!context->getExtensions().geometryShader)
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002953 {
2954 // It is an invalid operation to call DrawElements, DrawRangeElements or
2955 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2956 // 86)
Jamie Madill1e853262018-12-21 09:07:38 -05002957 return kUnsupportedDrawModeForTransformFeedback;
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002958 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002959 }
2960
Jamie Madillf5c88e72018-12-08 09:56:38 -05002961 const VertexArray *vao = state.getVertexArray();
2962 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
2963
2964 if (elementArrayBuffer)
2965 {
2966 if (context->getExtensions().webglCompatibility)
2967 {
2968 if (elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
2969 {
Jamie Madill1e853262018-12-21 09:07:38 -05002970 return kElementArrayBufferBoundForTransformFeedback;
Jamie Madillf5c88e72018-12-08 09:56:38 -05002971 }
2972 }
2973 else if (elementArrayBuffer->isMapped())
2974 {
2975 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
2976 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the
2977 // WebGL 2.0 API. https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madill1e853262018-12-21 09:07:38 -05002978 return kBufferMapped;
Jamie Madillf5c88e72018-12-08 09:56:38 -05002979 }
2980 }
2981 else
2982 {
2983 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2984 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
2985 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
2986 if (!context->getGLState().areClientArraysEnabled() ||
2987 context->getExtensions().webglCompatibility)
2988 {
Jamie Madill1e853262018-12-21 09:07:38 -05002989 return kMustHaveElementArrayBinding;
Jamie Madillf5c88e72018-12-08 09:56:38 -05002990 }
2991 }
2992
Jamie Madill1e853262018-12-21 09:07:38 -05002993 return nullptr;
Jiajia Qind9671222016-11-29 16:30:31 +08002994}
2995
Jamie Madill5b772312018-03-08 20:28:32 -05002996bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002997 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002998 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05002999 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04003000 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003001 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003002{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003003 if (!ValidateDrawElementsBase(context, mode, type))
Jamie Madillf5c88e72018-12-08 09:56:38 -05003004 {
Jiajia Qind9671222016-11-29 16:30:31 +08003005 return false;
Jamie Madillf5c88e72018-12-08 09:56:38 -05003006 }
Jiajia Qind9671222016-11-29 16:30:31 +08003007
Corentin Wallez170efbf2017-05-02 13:45:01 -04003008 if (!ValidateDrawBase(context, mode, count))
3009 {
3010 return false;
3011 }
3012
Jamie Madillf5c88e72018-12-08 09:56:38 -05003013 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04003014 const VertexArray *vao = state.getVertexArray();
Jamie Madillcd0a0a32018-10-18 18:41:57 -04003015 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003016
Jamie Madill8dc27f92018-11-29 11:45:44 -05003017 GLuint typeBytes = GetDrawElementsTypeSize(type);
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003018 ASSERT(isPow2(typeBytes) && typeBytes > 0);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003019
3020 if (context->getExtensions().webglCompatibility)
3021 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003022 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3023 {
3024 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3025 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3026 // data type passed to the call, or an INVALID_OPERATION error is generated.
Jamie Madille0472f32018-11-27 16:32:45 -05003027 context->validationError(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003028 return false;
3029 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003030
3031 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3032 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3033 // error is generated.
3034 if (reinterpret_cast<intptr_t>(indices) < 0)
3035 {
Jamie Madille0472f32018-11-27 16:32:45 -05003036 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003037 return false;
3038 }
Jamie Madillf5c88e72018-12-08 09:56:38 -05003039 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003040
Jamie Madillf5c88e72018-12-08 09:56:38 -05003041 // Early exit.
3042 if (count == 0)
3043 {
3044 return true;
3045 }
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003046
Jamie Madillf5c88e72018-12-08 09:56:38 -05003047 if (!elementArrayBuffer)
3048 {
3049 if (!indices)
James Darpiniane8a93c62018-01-04 18:02:24 -08003050 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003051 // This is an application error that would normally result in a crash, but we catch
3052 // it and return an error
3053 context->validationError(GL_INVALID_OPERATION, kElementArrayNoBufferOrPointer);
James Darpiniane8a93c62018-01-04 18:02:24 -08003054 return false;
3055 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003056 }
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003057 else
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003058 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003059 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3060 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3061 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3062 constexpr uint64_t kMaxTypeSize = 8;
3063 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3064 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3065 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3066
3067 uint64_t typeSize = typeBytes;
3068 uint64_t elementCount = static_cast<uint64_t>(count);
3069 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3070
3071 // Doing the multiplication here is overflow-safe
3072 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3073
3074 // The offset can be any value, check for overflows
3075 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3076 if (elementDataSizeNoOffset > kUint64Max - offset)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003077 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003078 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
3079 return false;
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003080 }
Jamie Madillf5c88e72018-12-08 09:56:38 -05003081
3082 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3083 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003084 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003085 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003086 return false;
3087 }
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003088 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003089
Jamie Madillf5c88e72018-12-08 09:56:38 -05003090 if (!context->getExtensions().robustBufferAccessBehavior && primcount > 0)
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003091 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003092 // Use the parameter buffer to retrieve and cache the index range.
3093 IndexRange indexRange;
3094 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
3095
3096 // If we use an index greater than our maximum supported index range, return an error.
3097 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
3098 // always return an error if possible here.
3099 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003100 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003101 context->validationError(GL_INVALID_OPERATION, kExceedsMaxElement);
3102 return false;
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003103 }
3104
Jamie Madillf5c88e72018-12-08 09:56:38 -05003105 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003106 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003107 return false;
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003108 }
Jamie Madillf5c88e72018-12-08 09:56:38 -05003109
3110 // No op if there are no real indices in the index data (all are primitive restart).
3111 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003112 }
3113
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003114 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003115}
3116
Jamie Madill5b772312018-03-08 20:28:32 -05003117bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003118 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003119 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05003120 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04003121 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003122 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003123{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003124 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003125}
3126
Geoff Lang3edfe032015-09-04 16:38:24 -04003127bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003128 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003129 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05003130 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04003131 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003132 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003133{
Geoff Lang63c5a592017-09-27 14:08:16 -04003134 if (!context->getExtensions().instancedArrays)
3135 {
Jamie Madille0472f32018-11-27 16:32:45 -05003136 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang63c5a592017-09-27 14:08:16 -04003137 return false;
3138 }
3139
Corentin Wallez170efbf2017-05-02 13:45:01 -04003140 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003141 {
3142 return false;
3143 }
3144
Corentin Wallez0dc97812017-06-22 14:38:44 -04003145 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003146}
3147
He Yunchaoced53ae2016-11-29 15:00:51 +08003148bool ValidateFramebufferTextureBase(Context *context,
3149 GLenum target,
3150 GLenum attachment,
3151 GLuint texture,
3152 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003153{
Geoff Lange8afa902017-09-27 15:00:43 -04003154 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003155 {
Jamie Madille0472f32018-11-27 16:32:45 -05003156 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003157 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003158 }
3159
3160 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003161 {
3162 return false;
3163 }
3164
Jamie Madill55ec3b12014-07-03 10:38:57 -04003165 if (texture != 0)
3166 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003167 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003168
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003169 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003170 {
Jamie Madille0472f32018-11-27 16:32:45 -05003171 context->validationError(GL_INVALID_OPERATION, kMissingTexture);
Geoff Langb1196682014-07-23 13:47:29 -04003172 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003173 }
3174
3175 if (level < 0)
3176 {
Jamie Madille0472f32018-11-27 16:32:45 -05003177 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003179 }
3180 }
3181
Jamie Madill43da7c42018-08-01 11:34:49 -04003182 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003183 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003184
Jamie Madill84115c92015-04-23 15:00:07 -04003185 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003186 {
Jamie Madille0472f32018-11-27 16:32:45 -05003187 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003188 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003189 }
3190
3191 return true;
3192}
3193
Geoff Langb1196682014-07-23 13:47:29 -04003194bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003195{
3196 if (program == 0)
3197 {
Jamie Madille0472f32018-11-27 16:32:45 -05003198 context->validationError(GL_INVALID_VALUE, kProgramDoesNotExist);
Geoff Langb1196682014-07-23 13:47:29 -04003199 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003200 }
3201
Jamie Madill43da7c42018-08-01 11:34:49 -04003202 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003203 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003204 {
3205 return false;
3206 }
3207
Jamie Madill0063c512014-08-25 15:47:53 -04003208 if (!programObject || !programObject->isLinked())
3209 {
Jamie Madille0472f32018-11-27 16:32:45 -05003210 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003211 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003212 }
3213
Geoff Lang7dd2e102014-11-10 15:19:26 -05003214 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003215 {
Jamie Madille0472f32018-11-27 16:32:45 -05003216 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
Geoff Langb1196682014-07-23 13:47:29 -04003217 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003218 }
3219
Jamie Madill0063c512014-08-25 15:47:53 -04003220 return true;
3221}
3222
Geoff Langf41d0ee2016-10-07 13:04:23 -04003223static bool ValidateSizedGetUniform(Context *context,
3224 GLuint program,
3225 GLint location,
3226 GLsizei bufSize,
3227 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003228{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003229 if (length)
3230 {
3231 *length = 0;
3232 }
3233
Jamie Madill78f41802014-08-25 15:47:55 -04003234 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003235 {
Jamie Madill78f41802014-08-25 15:47:55 -04003236 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003237 }
3238
Geoff Langf41d0ee2016-10-07 13:04:23 -04003239 if (bufSize < 0)
3240 {
Jamie Madille0472f32018-11-27 16:32:45 -05003241 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003242 return false;
3243 }
3244
Jamie Madill44a6fbf2018-10-02 13:38:56 -04003245 Program *programObject = context->getProgramResolveLink(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003246 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003247
Jamie Madill78f41802014-08-25 15:47:55 -04003248 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003249 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003250 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003251 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003252 {
Jamie Madille0472f32018-11-27 16:32:45 -05003253 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003254 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003255 }
3256
Geoff Langf41d0ee2016-10-07 13:04:23 -04003257 if (length)
3258 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003259 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003260 }
3261
Jamie Madill0063c512014-08-25 15:47:53 -04003262 return true;
3263}
3264
He Yunchaoced53ae2016-11-29 15:00:51 +08003265bool ValidateGetnUniformfvEXT(Context *context,
3266 GLuint program,
3267 GLint location,
3268 GLsizei bufSize,
3269 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003270{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003271 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003272}
3273
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003274bool ValidateGetnUniformfvRobustANGLE(Context *context,
3275 GLuint program,
3276 GLint location,
3277 GLsizei bufSize,
3278 GLsizei *length,
3279 GLfloat *params)
3280{
3281 UNIMPLEMENTED();
3282 return false;
3283}
3284
He Yunchaoced53ae2016-11-29 15:00:51 +08003285bool ValidateGetnUniformivEXT(Context *context,
3286 GLuint program,
3287 GLint location,
3288 GLsizei bufSize,
3289 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003290{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003291 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3292}
3293
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003294bool ValidateGetnUniformivRobustANGLE(Context *context,
3295 GLuint program,
3296 GLint location,
3297 GLsizei bufSize,
3298 GLsizei *length,
3299 GLint *params)
3300{
3301 UNIMPLEMENTED();
3302 return false;
3303}
3304
3305bool ValidateGetnUniformuivRobustANGLE(Context *context,
3306 GLuint program,
3307 GLint location,
3308 GLsizei bufSize,
3309 GLsizei *length,
3310 GLuint *params)
3311{
3312 UNIMPLEMENTED();
3313 return false;
3314}
3315
Geoff Langf41d0ee2016-10-07 13:04:23 -04003316bool ValidateGetUniformfvRobustANGLE(Context *context,
3317 GLuint program,
3318 GLint location,
3319 GLsizei bufSize,
3320 GLsizei *length,
3321 GLfloat *params)
3322{
3323 if (!ValidateRobustEntryPoint(context, bufSize))
3324 {
3325 return false;
3326 }
3327
Brandon Jonesd1049182018-03-28 10:02:20 -07003328 GLsizei writeLength = 0;
3329
Geoff Langf41d0ee2016-10-07 13:04:23 -04003330 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003331 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3332 {
3333 return false;
3334 }
3335
3336 SetRobustLengthParam(length, writeLength);
3337
3338 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003339}
3340
3341bool ValidateGetUniformivRobustANGLE(Context *context,
3342 GLuint program,
3343 GLint location,
3344 GLsizei bufSize,
3345 GLsizei *length,
3346 GLint *params)
3347{
3348 if (!ValidateRobustEntryPoint(context, bufSize))
3349 {
3350 return false;
3351 }
3352
Brandon Jonesd1049182018-03-28 10:02:20 -07003353 GLsizei writeLength = 0;
3354
Geoff Langf41d0ee2016-10-07 13:04:23 -04003355 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003356 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3357 {
3358 return false;
3359 }
3360
3361 SetRobustLengthParam(length, writeLength);
3362
3363 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003364}
3365
3366bool ValidateGetUniformuivRobustANGLE(Context *context,
3367 GLuint program,
3368 GLint location,
3369 GLsizei bufSize,
3370 GLsizei *length,
3371 GLuint *params)
3372{
3373 if (!ValidateRobustEntryPoint(context, bufSize))
3374 {
3375 return false;
3376 }
3377
3378 if (context->getClientMajorVersion() < 3)
3379 {
Jamie Madille0472f32018-11-27 16:32:45 -05003380 context->validationError(GL_INVALID_OPERATION, kES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003381 return false;
3382 }
3383
Brandon Jonesd1049182018-03-28 10:02:20 -07003384 GLsizei writeLength = 0;
3385
Geoff Langf41d0ee2016-10-07 13:04:23 -04003386 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003387 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3388 {
3389 return false;
3390 }
3391
3392 SetRobustLengthParam(length, writeLength);
3393
3394 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003395}
3396
He Yunchaoced53ae2016-11-29 15:00:51 +08003397bool ValidateDiscardFramebufferBase(Context *context,
3398 GLenum target,
3399 GLsizei numAttachments,
3400 const GLenum *attachments,
3401 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003402{
3403 if (numAttachments < 0)
3404 {
Jamie Madille0472f32018-11-27 16:32:45 -05003405 context->validationError(GL_INVALID_VALUE, kNegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003406 return false;
3407 }
3408
3409 for (GLsizei i = 0; i < numAttachments; ++i)
3410 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003411 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003412 {
3413 if (defaultFramebuffer)
3414 {
Jamie Madille0472f32018-11-27 16:32:45 -05003415 context->validationError(GL_INVALID_ENUM, kDefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003416 return false;
3417 }
3418
3419 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3420 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003421 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003422 return false;
3423 }
3424 }
3425 else
3426 {
3427 switch (attachments[i])
3428 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003429 case GL_DEPTH_ATTACHMENT:
3430 case GL_STENCIL_ATTACHMENT:
3431 case GL_DEPTH_STENCIL_ATTACHMENT:
3432 if (defaultFramebuffer)
3433 {
Jamie Madill610640f2018-11-21 17:28:41 -05003434 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05003435 kDefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003436 return false;
3437 }
3438 break;
3439 case GL_COLOR:
3440 case GL_DEPTH:
3441 case GL_STENCIL:
3442 if (!defaultFramebuffer)
3443 {
Jamie Madill610640f2018-11-21 17:28:41 -05003444 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05003445 kDefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003446 return false;
3447 }
3448 break;
3449 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003450 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003451 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003452 }
3453 }
3454 }
3455
3456 return true;
3457}
3458
Austin Kinross6ee1e782015-05-29 17:05:37 -07003459bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3460{
Jamie Madill007530e2017-12-28 14:27:04 -05003461 if (!context->getExtensions().debugMarker)
3462 {
3463 // The debug marker calls should not set error state
3464 // However, it seems reasonable to set an error state if the extension is not enabled
Jamie Madille0472f32018-11-27 16:32:45 -05003465 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill007530e2017-12-28 14:27:04 -05003466 return false;
3467 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003468
Jamie Madill007530e2017-12-28 14:27:04 -05003469 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003470 if (length < 0)
3471 {
3472 return false;
3473 }
3474
3475 if (marker == nullptr)
3476 {
3477 return false;
3478 }
3479
3480 return true;
3481}
3482
3483bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3484{
Jamie Madill007530e2017-12-28 14:27:04 -05003485 if (!context->getExtensions().debugMarker)
3486 {
3487 // The debug marker calls should not set error state
3488 // However, it seems reasonable to set an error state if the extension is not enabled
Jamie Madille0472f32018-11-27 16:32:45 -05003489 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill007530e2017-12-28 14:27:04 -05003490 return false;
3491 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003492
Jamie Madill007530e2017-12-28 14:27:04 -05003493 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003494 if (length < 0)
3495 {
3496 return false;
3497 }
3498
3499 if (length > 0 && marker == nullptr)
3500 {
3501 return false;
3502 }
3503
3504 return true;
3505}
3506
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003507bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003508{
Geoff Langa8406172015-07-21 16:53:39 -04003509 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3510 {
Jamie Madille0472f32018-11-27 16:32:45 -05003511 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langa8406172015-07-21 16:53:39 -04003512 return false;
3513 }
3514
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003515 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003516 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003517 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003518 if (!context->getExtensions().eglImage)
3519 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003520 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb66a9092016-05-16 15:59:14 -04003521 }
3522 break;
3523
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003524 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003525 if (!context->getExtensions().eglImageExternal)
3526 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003527 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb66a9092016-05-16 15:59:14 -04003528 }
Geoff Langa8406172015-07-21 16:53:39 -04003529 break;
3530
3531 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003532 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003533 return false;
3534 }
3535
Rafael Cintron05a449a2018-06-20 18:08:04 -07003536 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003537
Jamie Madill61e16b42017-06-19 11:13:23 -04003538 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003539 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003540 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003541 context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
Geoff Langa8406172015-07-21 16:53:39 -04003542 return false;
3543 }
3544
Jamie Madill007530e2017-12-28 14:27:04 -05003545 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003546 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003547 context->validationError(GL_INVALID_OPERATION, kEGLImageCannotCreate2DMultisampled);
Geoff Langa8406172015-07-21 16:53:39 -04003548 return false;
3549 }
3550
Yuly Novikov2eb54072018-08-22 16:41:26 -04003551 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003552 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003553 context->validationError(GL_INVALID_OPERATION, kEGLImageTextureFormatNotSupported);
Geoff Langa8406172015-07-21 16:53:39 -04003554 return false;
3555 }
3556
Geoff Langdcab33b2015-07-21 13:03:16 -04003557 return true;
3558}
3559
3560bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003561 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003562 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003563{
Geoff Langa8406172015-07-21 16:53:39 -04003564 if (!context->getExtensions().eglImage)
3565 {
Jamie Madille0472f32018-11-27 16:32:45 -05003566 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langa8406172015-07-21 16:53:39 -04003567 return false;
3568 }
3569
3570 switch (target)
3571 {
3572 case GL_RENDERBUFFER:
3573 break;
3574
3575 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003576 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003577 return false;
3578 }
3579
Rafael Cintron05a449a2018-06-20 18:08:04 -07003580 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003581
Jamie Madill61e16b42017-06-19 11:13:23 -04003582 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003583 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003584 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003585 context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
Geoff Langa8406172015-07-21 16:53:39 -04003586 return false;
3587 }
3588
Yuly Novikov2eb54072018-08-22 16:41:26 -04003589 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003590 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003591 context->validationError(GL_INVALID_OPERATION, kEGLImageRenderbufferFormatNotSupported);
Geoff Langa8406172015-07-21 16:53:39 -04003592 return false;
3593 }
3594
Geoff Langdcab33b2015-07-21 13:03:16 -04003595 return true;
3596}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003597
3598bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3599{
Geoff Lang36167ab2015-12-07 10:27:14 -05003600 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003601 {
3602 // The default VAO should always exist
3603 ASSERT(array != 0);
Jamie Madille0472f32018-11-27 16:32:45 -05003604 context->validationError(GL_INVALID_OPERATION, kInvalidVertexArray);
Austin Kinrossbc781f32015-10-26 09:27:38 -07003605 return false;
3606 }
3607
3608 return true;
3609}
3610
Geoff Langc5629752015-12-07 16:29:04 -05003611bool ValidateProgramBinaryBase(Context *context,
3612 GLuint program,
3613 GLenum binaryFormat,
3614 const void *binary,
3615 GLint length)
3616{
3617 Program *programObject = GetValidProgram(context, program);
3618 if (programObject == nullptr)
3619 {
3620 return false;
3621 }
3622
3623 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3624 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3625 programBinaryFormats.end())
3626 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003627 context->validationError(GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
Geoff Langc5629752015-12-07 16:29:04 -05003628 return false;
3629 }
3630
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003631 if (context->hasActiveTransformFeedback(program))
3632 {
3633 // ES 3.0.4 section 2.15 page 91
Jamie Madillc3e37312018-11-30 15:25:39 -05003634 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003635 return false;
3636 }
3637
Geoff Langc5629752015-12-07 16:29:04 -05003638 return true;
3639}
3640
3641bool ValidateGetProgramBinaryBase(Context *context,
3642 GLuint program,
3643 GLsizei bufSize,
3644 GLsizei *length,
3645 GLenum *binaryFormat,
3646 void *binary)
3647{
3648 Program *programObject = GetValidProgram(context, program);
3649 if (programObject == nullptr)
3650 {
3651 return false;
3652 }
3653
3654 if (!programObject->isLinked())
3655 {
Jamie Madille0472f32018-11-27 16:32:45 -05003656 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003657 return false;
3658 }
3659
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003660 if (context->getCaps().programBinaryFormats.empty())
3661 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003662 context->validationError(GL_INVALID_OPERATION, kNoProgramBinaryFormats);
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003663 return false;
3664 }
3665
Geoff Langc5629752015-12-07 16:29:04 -05003666 return true;
3667}
Jamie Madillc29968b2016-01-20 11:17:23 -05003668
Jamie Madill5b772312018-03-08 20:28:32 -05003669bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003670{
3671 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003672 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003673 {
Jamie Madille0472f32018-11-27 16:32:45 -05003674 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Brandon Jonesafa75152017-07-21 13:11:29 -07003675 return false;
3676 }
3677 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3678 {
Jamie Madille0472f32018-11-27 16:32:45 -05003679 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003680 return false;
3681 }
3682
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003683 ASSERT(context->getGLState().getDrawFramebuffer());
3684 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003685 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3686
3687 // This should come first before the check for the default frame buffer
3688 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3689 // rather than INVALID_OPERATION
3690 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3691 {
3692 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3693
3694 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003695 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3696 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003697 {
3698 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003699 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3700 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3701 // 3.1 is still a bit ambiguous about the error, but future specs are
3702 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madillc3e37312018-11-30 15:25:39 -05003703 context->validationError(GL_INVALID_ENUM, kInvalidDrawBuffer);
Olli Etuaho84c9f592016-03-09 14:37:25 +02003704 return false;
3705 }
3706 else if (bufs[colorAttachment] >= maxColorAttachment)
3707 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003708 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
Jamie Madillc29968b2016-01-20 11:17:23 -05003709 return false;
3710 }
3711 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3712 frameBufferId != 0)
3713 {
3714 // INVALID_OPERATION-GL is bound to buffer and ith argument
3715 // is not COLOR_ATTACHMENTi or NONE
Jamie Madillc3e37312018-11-30 15:25:39 -05003716 context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferValue);
Jamie Madillc29968b2016-01-20 11:17:23 -05003717 return false;
3718 }
3719 }
3720
3721 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3722 // and n is not 1 or bufs is bound to value other than BACK and NONE
3723 if (frameBufferId == 0)
3724 {
3725 if (n != 1)
3726 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003727 context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferCountForDefault);
Jamie Madillc29968b2016-01-20 11:17:23 -05003728 return false;
3729 }
3730
3731 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3732 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003733 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferInvalidDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003734 return false;
3735 }
3736 }
3737
3738 return true;
3739}
3740
Geoff Lang496c02d2016-10-20 11:38:11 -07003741bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003742 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003743 GLenum pname,
3744 GLsizei *length,
3745 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003746{
Geoff Lang496c02d2016-10-20 11:38:11 -07003747 if (length)
3748 {
3749 *length = 0;
3750 }
3751
Corentin Walleze4477002017-12-01 14:39:58 -05003752 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003753 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003754 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003755 return false;
3756 }
3757
Geoff Lang496c02d2016-10-20 11:38:11 -07003758 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003759 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003760 case GL_BUFFER_MAP_POINTER:
3761 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003762
Geoff Lang496c02d2016-10-20 11:38:11 -07003763 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003764 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003765 return false;
3766 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003767
3768 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3769 // target bound to zero generate an INVALID_OPERATION error."
3770 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003771 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003772 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003773 context->validationError(GL_INVALID_OPERATION, kBufferPointerNotAvailable);
Olli Etuaho4f667482016-03-30 15:56:35 +03003774 return false;
3775 }
3776
Geoff Lang496c02d2016-10-20 11:38:11 -07003777 if (length)
3778 {
3779 *length = 1;
3780 }
3781
Olli Etuaho4f667482016-03-30 15:56:35 +03003782 return true;
3783}
3784
Corentin Wallez336129f2017-10-17 15:55:40 -04003785bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003786{
Corentin Walleze4477002017-12-01 14:39:58 -05003787 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003788 {
Jamie Madille0472f32018-11-27 16:32:45 -05003789 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003790 return false;
3791 }
3792
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003793 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003794
3795 if (buffer == nullptr || !buffer->isMapped())
3796 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003797 context->validationError(GL_INVALID_OPERATION, kBufferNotMapped);
Olli Etuaho4f667482016-03-30 15:56:35 +03003798 return false;
3799 }
3800
3801 return true;
3802}
3803
3804bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003805 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003806 GLintptr offset,
3807 GLsizeiptr length,
3808 GLbitfield access)
3809{
Corentin Walleze4477002017-12-01 14:39:58 -05003810 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003811 {
Jamie Madille0472f32018-11-27 16:32:45 -05003812 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003813 return false;
3814 }
3815
Brandon Jones6cad5662017-06-14 13:25:13 -07003816 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003817 {
Jamie Madille0472f32018-11-27 16:32:45 -05003818 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07003819 return false;
3820 }
3821
3822 if (length < 0)
3823 {
Jamie Madille0472f32018-11-27 16:32:45 -05003824 context->validationError(GL_INVALID_VALUE, kNegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003825 return false;
3826 }
3827
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003828 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003829
3830 if (!buffer)
3831 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003832 context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
Olli Etuaho4f667482016-03-30 15:56:35 +03003833 return false;
3834 }
3835
3836 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003837 CheckedNumeric<size_t> checkedOffset(offset);
3838 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003839
Jamie Madille2e406c2016-06-02 13:04:10 -04003840 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003841 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003842 context->validationError(GL_INVALID_VALUE, kMapOutOfRange);
Olli Etuaho4f667482016-03-30 15:56:35 +03003843 return false;
3844 }
3845
3846 // Check for invalid bits in the mask
3847 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3848 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3849 GL_MAP_UNSYNCHRONIZED_BIT;
3850
3851 if (access & ~(allAccessBits))
3852 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003853 context->validationError(GL_INVALID_VALUE, kInvalidAccessBits);
Olli Etuaho4f667482016-03-30 15:56:35 +03003854 return false;
3855 }
3856
3857 if (length == 0)
3858 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003859 context->validationError(GL_INVALID_OPERATION, kLengthZero);
Olli Etuaho4f667482016-03-30 15:56:35 +03003860 return false;
3861 }
3862
3863 if (buffer->isMapped())
3864 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003865 context->validationError(GL_INVALID_OPERATION, kBufferAlreadyMapped);
Olli Etuaho4f667482016-03-30 15:56:35 +03003866 return false;
3867 }
3868
3869 // Check for invalid bit combinations
3870 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3871 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003872 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
Olli Etuaho4f667482016-03-30 15:56:35 +03003873 return false;
3874 }
3875
3876 GLbitfield writeOnlyBits =
3877 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3878
3879 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3880 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003881 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsRead);
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 return false;
3883 }
3884
3885 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3886 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003887 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
Olli Etuaho4f667482016-03-30 15:56:35 +03003888 return false;
3889 }
Geoff Lang79f71042017-08-14 16:43:43 -04003890
3891 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003892}
3893
3894bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003895 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003896 GLintptr offset,
3897 GLsizeiptr length)
3898{
Brandon Jones6cad5662017-06-14 13:25:13 -07003899 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 {
Jamie Madille0472f32018-11-27 16:32:45 -05003901 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07003902 return false;
3903 }
3904
3905 if (length < 0)
3906 {
Jamie Madille0472f32018-11-27 16:32:45 -05003907 context->validationError(GL_INVALID_VALUE, kNegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 return false;
3909 }
3910
Corentin Walleze4477002017-12-01 14:39:58 -05003911 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003912 {
Jamie Madille0472f32018-11-27 16:32:45 -05003913 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 return false;
3915 }
3916
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003917 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003918
3919 if (buffer == nullptr)
3920 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003921 context->validationError(GL_INVALID_OPERATION, kInvalidFlushZero);
Olli Etuaho4f667482016-03-30 15:56:35 +03003922 return false;
3923 }
3924
3925 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3926 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003927 context->validationError(GL_INVALID_OPERATION, kInvalidFlushTarget);
Olli Etuaho4f667482016-03-30 15:56:35 +03003928 return false;
3929 }
3930
3931 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003932 CheckedNumeric<size_t> checkedOffset(offset);
3933 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003934
Jamie Madille2e406c2016-06-02 13:04:10 -04003935 if (!checkedSize.IsValid() ||
3936 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003937 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003938 context->validationError(GL_INVALID_VALUE, kInvalidFlushOutOfRange);
Olli Etuaho4f667482016-03-30 15:56:35 +03003939 return false;
3940 }
3941
3942 return true;
3943}
3944
Olli Etuaho41997e72016-03-10 13:38:39 +02003945bool ValidateGenOrDelete(Context *context, GLint n)
3946{
3947 if (n < 0)
3948 {
Jamie Madille0472f32018-11-27 16:32:45 -05003949 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003950 return false;
3951 }
3952 return true;
3953}
3954
Jamie Madill5b772312018-03-08 20:28:32 -05003955bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003956{
3957 if (!context->getExtensions().robustClientMemory)
3958 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003959 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langff5b2d52016-09-07 11:32:23 -04003960 return false;
3961 }
3962
3963 if (bufSize < 0)
3964 {
Jamie Madille0472f32018-11-27 16:32:45 -05003965 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003966 return false;
3967 }
3968
3969 return true;
3970}
3971
Jamie Madill5b772312018-03-08 20:28:32 -05003972bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003973{
3974 if (bufSize < numParams)
3975 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003976 context->validationError(GL_INVALID_OPERATION, kInsufficientParams);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003977 return false;
3978 }
3979
3980 return true;
3981}
3982
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003983bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003984 GLenum target,
3985 GLenum attachment,
3986 GLenum pname,
3987 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003988{
Geoff Lange8afa902017-09-27 15:00:43 -04003989 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003990 {
Jamie Madille0472f32018-11-27 16:32:45 -05003991 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003992 return false;
3993 }
3994
3995 int clientVersion = context->getClientMajorVersion();
3996
3997 switch (pname)
3998 {
3999 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4000 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4001 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4002 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4003 break;
4004
Martin Radeve5285d22017-07-14 16:23:53 +03004005 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4006 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4007 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4008 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4009 if (clientVersion < 3 || !context->getExtensions().multiview)
4010 {
Jamie Madille0472f32018-11-27 16:32:45 -05004011 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Martin Radeve5285d22017-07-14 16:23:53 +03004012 return false;
4013 }
4014 break;
4015
Geoff Langff5b2d52016-09-07 11:32:23 -04004016 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4017 if (clientVersion < 3 && !context->getExtensions().sRGB)
4018 {
Jamie Madille0472f32018-11-27 16:32:45 -05004019 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004020 return false;
4021 }
4022 break;
4023
4024 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4025 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4026 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4027 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4028 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4029 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4030 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4031 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4032 if (clientVersion < 3)
4033 {
Jamie Madille0472f32018-11-27 16:32:45 -05004034 context->validationError(GL_INVALID_ENUM, kES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004035 return false;
4036 }
4037 break;
4038
Jiawei Shaoa8802472018-05-28 11:17:47 +08004039 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4040 if (!context->getExtensions().geometryShader)
4041 {
Jamie Madille0472f32018-11-27 16:32:45 -05004042 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shaoa8802472018-05-28 11:17:47 +08004043 return false;
4044 }
4045 break;
4046
Geoff Langff5b2d52016-09-07 11:32:23 -04004047 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004048 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Geoff Langff5b2d52016-09-07 11:32:23 -04004049 return false;
4050 }
4051
4052 // Determine if the attachment is a valid enum
4053 switch (attachment)
4054 {
4055 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004056 case GL_DEPTH:
4057 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004058 if (clientVersion < 3)
4059 {
Jamie Madille0472f32018-11-27 16:32:45 -05004060 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004061 return false;
4062 }
4063 break;
4064
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004065 case GL_DEPTH_STENCIL_ATTACHMENT:
4066 if (clientVersion < 3 && !context->isWebGL1())
4067 {
Jamie Madille0472f32018-11-27 16:32:45 -05004068 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004069 return false;
4070 }
4071 break;
4072
Geoff Langfa125c92017-10-24 13:01:46 -04004073 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004074 case GL_DEPTH_ATTACHMENT:
4075 case GL_STENCIL_ATTACHMENT:
4076 break;
4077
4078 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004079 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4080 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004081 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4082 {
Jamie Madille0472f32018-11-27 16:32:45 -05004083 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004084 return false;
4085 }
4086 break;
4087 }
4088
4089 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4090 ASSERT(framebuffer);
4091
4092 if (framebuffer->id() == 0)
4093 {
4094 if (clientVersion < 3)
4095 {
Jamie Madille0472f32018-11-27 16:32:45 -05004096 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 return false;
4098 }
4099
4100 switch (attachment)
4101 {
4102 case GL_BACK:
4103 case GL_DEPTH:
4104 case GL_STENCIL:
4105 break;
4106
4107 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004108 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004109 return false;
4110 }
4111 }
4112 else
4113 {
4114 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4115 {
4116 // Valid attachment query
4117 }
4118 else
4119 {
4120 switch (attachment)
4121 {
4122 case GL_DEPTH_ATTACHMENT:
4123 case GL_STENCIL_ATTACHMENT:
4124 break;
4125
4126 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004127 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004128 {
Jamie Madille0472f32018-11-27 16:32:45 -05004129 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004130 return false;
4131 }
4132 break;
4133
4134 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004135 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004136 return false;
4137 }
4138 }
4139 }
4140
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004141 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004142 if (attachmentObject)
4143 {
4144 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4145 attachmentObject->type() == GL_TEXTURE ||
4146 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4147
4148 switch (pname)
4149 {
4150 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4151 if (attachmentObject->type() != GL_RENDERBUFFER &&
4152 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_LEVEL:
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_TEXTURE_CUBE_MAP_FACE:
4168 if (attachmentObject->type() != GL_TEXTURE)
4169 {
Jamie Madille0472f32018-11-27 16:32:45 -05004170 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004171 return false;
4172 }
4173 break;
4174
4175 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4176 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4177 {
Jamie Madille0472f32018-11-27 16:32:45 -05004178 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004179 return false;
4180 }
4181 break;
4182
4183 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4184 if (attachmentObject->type() != GL_TEXTURE)
4185 {
Jamie Madille0472f32018-11-27 16:32:45 -05004186 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004187 return false;
4188 }
4189 break;
4190
4191 default:
4192 break;
4193 }
4194 }
4195 else
4196 {
4197 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4198 // is NONE, then querying any other pname will generate INVALID_ENUM.
4199
4200 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4201 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4202 // INVALID_OPERATION for all other pnames
4203
4204 switch (pname)
4205 {
4206 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4207 break;
4208
4209 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4210 if (clientVersion < 3)
4211 {
Jamie Madill610640f2018-11-21 17:28:41 -05004212 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05004213 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004214 return false;
4215 }
4216 break;
4217
4218 default:
4219 if (clientVersion < 3)
4220 {
Jamie Madill610640f2018-11-21 17:28:41 -05004221 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05004222 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004223 return false;
4224 }
4225 else
4226 {
Jamie Madill610640f2018-11-21 17:28:41 -05004227 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05004228 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004229 return false;
4230 }
4231 }
4232 }
4233
Martin Radeve5285d22017-07-14 16:23:53 +03004234 if (numParams)
4235 {
4236 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4237 {
4238 // Only when the viewport offsets are queried we can have a varying number of output
4239 // parameters.
4240 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4241 *numParams = numViews * 2;
4242 }
4243 else
4244 {
4245 // For all other queries we can have only one output parameter.
4246 *numParams = 1;
4247 }
4248 }
4249
Geoff Langff5b2d52016-09-07 11:32:23 -04004250 return true;
4251}
4252
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004253bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004254 GLenum target,
4255 GLenum attachment,
4256 GLenum pname,
4257 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004258 GLsizei *length,
4259 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004260{
4261 if (!ValidateRobustEntryPoint(context, bufSize))
4262 {
4263 return false;
4264 }
4265
Brandon Jonesd1049182018-03-28 10:02:20 -07004266 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004267 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004268 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004269 {
4270 return false;
4271 }
4272
Brandon Jonesd1049182018-03-28 10:02:20 -07004273 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004274 {
4275 return false;
4276 }
4277
Brandon Jonesd1049182018-03-28 10:02:20 -07004278 SetRobustLengthParam(length, numParams);
4279
Geoff Langff5b2d52016-09-07 11:32:23 -04004280 return true;
4281}
4282
Jamie Madill5b772312018-03-08 20:28:32 -05004283bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004284 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004285 GLenum pname,
4286 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004287 GLsizei *length,
4288 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004289{
4290 if (!ValidateRobustEntryPoint(context, bufSize))
4291 {
4292 return false;
4293 }
4294
Brandon Jonesd1049182018-03-28 10:02:20 -07004295 GLsizei numParams = 0;
4296
4297 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004298 {
4299 return false;
4300 }
4301
Brandon Jonesd1049182018-03-28 10:02:20 -07004302 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004303 {
4304 return false;
4305 }
4306
Brandon Jonesd1049182018-03-28 10:02:20 -07004307 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004308 return true;
4309}
4310
Jamie Madill5b772312018-03-08 20:28:32 -05004311bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004312 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004313 GLenum pname,
4314 GLsizei bufSize,
4315 GLsizei *length,
4316 GLint64 *params)
4317{
Brandon Jonesd1049182018-03-28 10:02:20 -07004318 GLsizei numParams = 0;
4319
Geoff Langebebe1c2016-10-14 12:01:31 -04004320 if (!ValidateRobustEntryPoint(context, bufSize))
4321 {
4322 return false;
4323 }
4324
Brandon Jonesd1049182018-03-28 10:02:20 -07004325 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004326 {
4327 return false;
4328 }
4329
Brandon Jonesd1049182018-03-28 10:02:20 -07004330 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004331 {
4332 return false;
4333 }
4334
Brandon Jonesd1049182018-03-28 10:02:20 -07004335 SetRobustLengthParam(length, numParams);
4336
Geoff Langff5b2d52016-09-07 11:32:23 -04004337 return true;
4338}
4339
Jamie Madill5b772312018-03-08 20:28:32 -05004340bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004341{
4342 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004343 if (numParams)
4344 {
4345 *numParams = 1;
4346 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004347
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004348 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
4349 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
4350 ? GetValidProgramNoResolve(context, program)
4351 : GetValidProgram(context, program);
Geoff Langff5b2d52016-09-07 11:32:23 -04004352 if (!programObject)
4353 {
4354 return false;
4355 }
4356
4357 switch (pname)
4358 {
4359 case GL_DELETE_STATUS:
4360 case GL_LINK_STATUS:
4361 case GL_VALIDATE_STATUS:
4362 case GL_INFO_LOG_LENGTH:
4363 case GL_ATTACHED_SHADERS:
4364 case GL_ACTIVE_ATTRIBUTES:
4365 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4366 case GL_ACTIVE_UNIFORMS:
4367 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4368 break;
4369
4370 case GL_PROGRAM_BINARY_LENGTH:
4371 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4372 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004373 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004374 return false;
4375 }
4376 break;
4377
4378 case GL_ACTIVE_UNIFORM_BLOCKS:
4379 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4380 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4381 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4382 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4383 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4384 if (context->getClientMajorVersion() < 3)
4385 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004386 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Geoff Langff5b2d52016-09-07 11:32:23 -04004387 return false;
4388 }
4389 break;
4390
Yunchao He61afff12017-03-14 15:34:03 +08004391 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004392 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004393 if (context->getClientVersion() < Version(3, 1))
4394 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004395 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Yunchao He61afff12017-03-14 15:34:03 +08004396 return false;
4397 }
4398 break;
4399
Jiawei Shao6ae51612018-02-23 14:03:25 +08004400 case GL_COMPUTE_WORK_GROUP_SIZE:
4401 if (context->getClientVersion() < Version(3, 1))
4402 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004403 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004404 return false;
4405 }
4406
4407 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4408 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4409 // program which has not been linked successfully, or which does not contain objects to
4410 // form a compute shader.
4411 if (!programObject->isLinked())
4412 {
Jamie Madille0472f32018-11-27 16:32:45 -05004413 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004414 return false;
4415 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004416 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004417 {
Jamie Madille0472f32018-11-27 16:32:45 -05004418 context->validationError(GL_INVALID_OPERATION, kNoActiveComputeShaderStage);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004419 return false;
4420 }
4421 break;
4422
Jiawei Shao447bfac2018-03-14 14:23:40 +08004423 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4424 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4425 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4426 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4427 if (!context->getExtensions().geometryShader)
4428 {
Jamie Madille0472f32018-11-27 16:32:45 -05004429 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004430 return false;
4431 }
4432
4433 // [EXT_geometry_shader] Chapter 7.12
4434 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4435 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4436 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4437 // successfully, or which does not contain objects to form a geometry shader.
4438 if (!programObject->isLinked())
4439 {
Jamie Madille0472f32018-11-27 16:32:45 -05004440 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004441 return false;
4442 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004443 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004444 {
Jamie Madille0472f32018-11-27 16:32:45 -05004445 context->validationError(GL_INVALID_OPERATION, kNoActiveGeometryShaderStage);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004446 return false;
4447 }
4448 break;
4449
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004450 case GL_COMPLETION_STATUS_KHR:
4451 if (!context->getExtensions().parallelShaderCompile)
4452 {
Jamie Madille0472f32018-11-27 16:32:45 -05004453 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004454 return false;
4455 }
4456 break;
4457
Geoff Langff5b2d52016-09-07 11:32:23 -04004458 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004459 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004460 return false;
4461 }
4462
4463 return true;
4464}
4465
4466bool ValidateGetProgramivRobustANGLE(Context *context,
4467 GLuint program,
4468 GLenum pname,
4469 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004470 GLsizei *length,
4471 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004472{
4473 if (!ValidateRobustEntryPoint(context, bufSize))
4474 {
4475 return false;
4476 }
4477
Brandon Jonesd1049182018-03-28 10:02:20 -07004478 GLsizei numParams = 0;
4479
4480 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004481 {
4482 return false;
4483 }
4484
Brandon Jonesd1049182018-03-28 10:02:20 -07004485 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004486 {
4487 return false;
4488 }
4489
Brandon Jonesd1049182018-03-28 10:02:20 -07004490 SetRobustLengthParam(length, numParams);
4491
Geoff Langff5b2d52016-09-07 11:32:23 -04004492 return true;
4493}
4494
Geoff Lang740d9022016-10-07 11:20:52 -04004495bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4496 GLenum target,
4497 GLenum pname,
4498 GLsizei bufSize,
4499 GLsizei *length,
4500 GLint *params)
4501{
4502 if (!ValidateRobustEntryPoint(context, bufSize))
4503 {
4504 return false;
4505 }
4506
Brandon Jonesd1049182018-03-28 10:02:20 -07004507 GLsizei numParams = 0;
4508
4509 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004510 {
4511 return false;
4512 }
4513
Brandon Jonesd1049182018-03-28 10:02:20 -07004514 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004515 {
4516 return false;
4517 }
4518
Brandon Jonesd1049182018-03-28 10:02:20 -07004519 SetRobustLengthParam(length, numParams);
4520
Geoff Lang740d9022016-10-07 11:20:52 -04004521 return true;
4522}
4523
Geoff Langd7d0ed32016-10-07 11:33:51 -04004524bool ValidateGetShaderivRobustANGLE(Context *context,
4525 GLuint shader,
4526 GLenum pname,
4527 GLsizei bufSize,
4528 GLsizei *length,
4529 GLint *params)
4530{
4531 if (!ValidateRobustEntryPoint(context, bufSize))
4532 {
4533 return false;
4534 }
4535
Brandon Jonesd1049182018-03-28 10:02:20 -07004536 GLsizei numParams = 0;
4537
4538 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004539 {
4540 return false;
4541 }
4542
Brandon Jonesd1049182018-03-28 10:02:20 -07004543 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004544 {
4545 return false;
4546 }
4547
Brandon Jonesd1049182018-03-28 10:02:20 -07004548 SetRobustLengthParam(length, numParams);
4549
Geoff Langd7d0ed32016-10-07 11:33:51 -04004550 return true;
4551}
4552
Geoff Langc1984ed2016-10-07 12:41:00 -04004553bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004554 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004555 GLenum pname,
4556 GLsizei bufSize,
4557 GLsizei *length,
4558 GLfloat *params)
4559{
4560 if (!ValidateRobustEntryPoint(context, bufSize))
4561 {
4562 return false;
4563 }
4564
Brandon Jonesd1049182018-03-28 10:02:20 -07004565 GLsizei numParams = 0;
4566
4567 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004568 {
4569 return false;
4570 }
4571
Brandon Jonesd1049182018-03-28 10:02:20 -07004572 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004573 {
4574 return false;
4575 }
4576
Brandon Jonesd1049182018-03-28 10:02:20 -07004577 SetRobustLengthParam(length, numParams);
4578
Geoff Langc1984ed2016-10-07 12:41:00 -04004579 return true;
4580}
4581
Geoff Langc1984ed2016-10-07 12:41:00 -04004582bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004583 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004584 GLenum pname,
4585 GLsizei bufSize,
4586 GLsizei *length,
4587 GLint *params)
4588{
Brandon Jonesd1049182018-03-28 10:02:20 -07004589
Geoff Langc1984ed2016-10-07 12:41:00 -04004590 if (!ValidateRobustEntryPoint(context, bufSize))
4591 {
4592 return false;
4593 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004594 GLsizei numParams = 0;
4595 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004596 {
4597 return false;
4598 }
4599
Brandon Jonesd1049182018-03-28 10:02:20 -07004600 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004601 {
4602 return false;
4603 }
4604
Brandon Jonesd1049182018-03-28 10:02:20 -07004605 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004606 return true;
4607}
4608
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004609bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4610 TextureType target,
4611 GLenum pname,
4612 GLsizei bufSize,
4613 GLsizei *length,
4614 GLint *params)
4615{
4616 UNIMPLEMENTED();
4617 return false;
4618}
4619
4620bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4621 TextureType target,
4622 GLenum pname,
4623 GLsizei bufSize,
4624 GLsizei *length,
4625 GLuint *params)
4626{
4627 UNIMPLEMENTED();
4628 return false;
4629}
4630
Geoff Langc1984ed2016-10-07 12:41:00 -04004631bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004632 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004633 GLenum pname,
4634 GLsizei bufSize,
4635 const GLfloat *params)
4636{
4637 if (!ValidateRobustEntryPoint(context, bufSize))
4638 {
4639 return false;
4640 }
4641
Till Rathmannb8543632018-10-02 19:46:14 +02004642 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004643}
4644
Geoff Langc1984ed2016-10-07 12:41:00 -04004645bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004646 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004647 GLenum pname,
4648 GLsizei bufSize,
4649 const GLint *params)
4650{
4651 if (!ValidateRobustEntryPoint(context, bufSize))
4652 {
4653 return false;
4654 }
4655
Till Rathmannb8543632018-10-02 19:46:14 +02004656 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004657}
4658
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004659bool ValidateTexParameterIivRobustANGLE(Context *context,
4660 TextureType target,
4661 GLenum pname,
4662 GLsizei bufSize,
4663 const GLint *params)
4664{
4665 UNIMPLEMENTED();
4666 return false;
4667}
4668
4669bool ValidateTexParameterIuivRobustANGLE(Context *context,
4670 TextureType target,
4671 GLenum pname,
4672 GLsizei bufSize,
4673 const GLuint *params)
4674{
4675 UNIMPLEMENTED();
4676 return false;
4677}
4678
Geoff Langc1984ed2016-10-07 12:41:00 -04004679bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4680 GLuint sampler,
4681 GLenum pname,
Jamie Madill778bf092018-11-14 09:54:36 -05004682 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004683 GLsizei *length,
4684 GLfloat *params)
4685{
4686 if (!ValidateRobustEntryPoint(context, bufSize))
4687 {
4688 return false;
4689 }
4690
Brandon Jonesd1049182018-03-28 10:02:20 -07004691 GLsizei numParams = 0;
4692
4693 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004694 {
4695 return false;
4696 }
4697
Brandon Jonesd1049182018-03-28 10:02:20 -07004698 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004699 {
4700 return false;
4701 }
4702
Brandon Jonesd1049182018-03-28 10:02:20 -07004703 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004704 return true;
4705}
4706
Geoff Langc1984ed2016-10-07 12:41:00 -04004707bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4708 GLuint sampler,
4709 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004710 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004711 GLsizei *length,
4712 GLint *params)
4713{
4714 if (!ValidateRobustEntryPoint(context, bufSize))
4715 {
4716 return false;
4717 }
4718
Brandon Jonesd1049182018-03-28 10:02:20 -07004719 GLsizei numParams = 0;
4720
4721 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004722 {
4723 return false;
4724 }
4725
Brandon Jonesd1049182018-03-28 10:02:20 -07004726 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004727 {
4728 return false;
4729 }
4730
Brandon Jonesd1049182018-03-28 10:02:20 -07004731 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004732 return true;
4733}
4734
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004735bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4736 GLuint sampler,
4737 GLenum pname,
4738 GLsizei bufSize,
4739 GLsizei *length,
4740 GLint *params)
4741{
4742 UNIMPLEMENTED();
4743 return false;
4744}
4745
4746bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4747 GLuint sampler,
4748 GLenum pname,
4749 GLsizei bufSize,
4750 GLsizei *length,
4751 GLuint *params)
4752{
4753 UNIMPLEMENTED();
4754 return false;
4755}
4756
Geoff Langc1984ed2016-10-07 12:41:00 -04004757bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4758 GLuint sampler,
4759 GLenum pname,
4760 GLsizei bufSize,
4761 const GLfloat *params)
4762{
4763 if (!ValidateRobustEntryPoint(context, bufSize))
4764 {
4765 return false;
4766 }
4767
Till Rathmannb8543632018-10-02 19:46:14 +02004768 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004769}
4770
Geoff Langc1984ed2016-10-07 12:41:00 -04004771bool ValidateSamplerParameterivRobustANGLE(Context *context,
4772 GLuint sampler,
4773 GLenum pname,
4774 GLsizei bufSize,
4775 const GLint *params)
4776{
4777 if (!ValidateRobustEntryPoint(context, bufSize))
4778 {
4779 return false;
4780 }
4781
Till Rathmannb8543632018-10-02 19:46:14 +02004782 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004783}
4784
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004785bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4786 GLuint sampler,
4787 GLenum pname,
4788 GLsizei bufSize,
4789 const GLint *param)
4790{
4791 UNIMPLEMENTED();
4792 return false;
4793}
4794
4795bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4796 GLuint sampler,
4797 GLenum pname,
4798 GLsizei bufSize,
4799 const GLuint *param)
4800{
4801 UNIMPLEMENTED();
4802 return false;
4803}
4804
Geoff Lang0b031062016-10-13 14:30:04 -04004805bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4806 GLuint index,
4807 GLenum pname,
4808 GLsizei bufSize,
4809 GLsizei *length,
4810 GLfloat *params)
4811{
4812 if (!ValidateRobustEntryPoint(context, bufSize))
4813 {
4814 return false;
4815 }
4816
Brandon Jonesd1049182018-03-28 10:02:20 -07004817 GLsizei writeLength = 0;
4818
4819 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004820 {
4821 return false;
4822 }
4823
Brandon Jonesd1049182018-03-28 10:02:20 -07004824 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004825 {
4826 return false;
4827 }
4828
Brandon Jonesd1049182018-03-28 10:02:20 -07004829 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004830 return true;
4831}
4832
Geoff Lang0b031062016-10-13 14:30:04 -04004833bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4834 GLuint index,
4835 GLenum pname,
4836 GLsizei bufSize,
4837 GLsizei *length,
4838 GLint *params)
4839{
4840 if (!ValidateRobustEntryPoint(context, bufSize))
4841 {
4842 return false;
4843 }
4844
Brandon Jonesd1049182018-03-28 10:02:20 -07004845 GLsizei writeLength = 0;
4846
4847 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004848 {
4849 return false;
4850 }
4851
Brandon Jonesd1049182018-03-28 10:02:20 -07004852 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004853 {
4854 return false;
4855 }
4856
Brandon Jonesd1049182018-03-28 10:02:20 -07004857 SetRobustLengthParam(length, writeLength);
4858
Geoff Lang0b031062016-10-13 14:30:04 -04004859 return true;
4860}
4861
Geoff Lang0b031062016-10-13 14:30:04 -04004862bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4863 GLuint index,
4864 GLenum pname,
4865 GLsizei bufSize,
4866 GLsizei *length,
4867 void **pointer)
4868{
4869 if (!ValidateRobustEntryPoint(context, bufSize))
4870 {
4871 return false;
4872 }
4873
Brandon Jonesd1049182018-03-28 10:02:20 -07004874 GLsizei writeLength = 0;
4875
4876 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004877 {
4878 return false;
4879 }
4880
Brandon Jonesd1049182018-03-28 10:02:20 -07004881 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004882 {
4883 return false;
4884 }
4885
Brandon Jonesd1049182018-03-28 10:02:20 -07004886 SetRobustLengthParam(length, writeLength);
4887
Geoff Lang0b031062016-10-13 14:30:04 -04004888 return true;
4889}
4890
Geoff Lang0b031062016-10-13 14:30:04 -04004891bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4892 GLuint index,
4893 GLenum pname,
4894 GLsizei bufSize,
4895 GLsizei *length,
4896 GLint *params)
4897{
4898 if (!ValidateRobustEntryPoint(context, bufSize))
4899 {
4900 return false;
4901 }
4902
Brandon Jonesd1049182018-03-28 10:02:20 -07004903 GLsizei writeLength = 0;
4904
4905 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004906 {
4907 return false;
4908 }
4909
Brandon Jonesd1049182018-03-28 10:02:20 -07004910 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004911 {
4912 return false;
4913 }
4914
Brandon Jonesd1049182018-03-28 10:02:20 -07004915 SetRobustLengthParam(length, writeLength);
4916
Geoff Lang0b031062016-10-13 14:30:04 -04004917 return true;
4918}
4919
Geoff Lang0b031062016-10-13 14:30:04 -04004920bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4921 GLuint index,
4922 GLenum pname,
4923 GLsizei bufSize,
4924 GLsizei *length,
4925 GLuint *params)
4926{
4927 if (!ValidateRobustEntryPoint(context, bufSize))
4928 {
4929 return false;
4930 }
4931
Brandon Jonesd1049182018-03-28 10:02:20 -07004932 GLsizei writeLength = 0;
4933
4934 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004935 {
4936 return false;
4937 }
4938
Brandon Jonesd1049182018-03-28 10:02:20 -07004939 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004940 {
4941 return false;
4942 }
4943
Brandon Jonesd1049182018-03-28 10:02:20 -07004944 SetRobustLengthParam(length, writeLength);
4945
Geoff Lang0b031062016-10-13 14:30:04 -04004946 return true;
4947}
4948
Geoff Lang6899b872016-10-14 11:30:13 -04004949bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4950 GLuint program,
4951 GLuint uniformBlockIndex,
4952 GLenum pname,
4953 GLsizei bufSize,
4954 GLsizei *length,
4955 GLint *params)
4956{
4957 if (!ValidateRobustEntryPoint(context, bufSize))
4958 {
4959 return false;
4960 }
4961
Brandon Jonesd1049182018-03-28 10:02:20 -07004962 GLsizei writeLength = 0;
4963
4964 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4965 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004966 {
4967 return false;
4968 }
4969
Brandon Jonesd1049182018-03-28 10:02:20 -07004970 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004971 {
4972 return false;
4973 }
4974
Brandon Jonesd1049182018-03-28 10:02:20 -07004975 SetRobustLengthParam(length, writeLength);
4976
Geoff Lang6899b872016-10-14 11:30:13 -04004977 return true;
4978}
4979
Brandon Jones416aaf92018-04-10 08:10:16 -07004980bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004981 GLenum target,
4982 GLenum internalformat,
4983 GLenum pname,
4984 GLsizei bufSize,
4985 GLsizei *length,
4986 GLint *params)
4987{
4988 if (!ValidateRobustEntryPoint(context, bufSize))
4989 {
4990 return false;
4991 }
4992
Brandon Jonesd1049182018-03-28 10:02:20 -07004993 GLsizei numParams = 0;
4994
4995 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4996 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07004997 {
4998 return false;
4999 }
5000
Brandon Jonesd1049182018-03-28 10:02:20 -07005001 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005002 {
5003 return false;
5004 }
5005
Brandon Jonesd1049182018-03-28 10:02:20 -07005006 SetRobustLengthParam(length, numParams);
5007
Geoff Lang0a9661f2016-10-20 10:59:20 -07005008 return true;
5009}
5010
Jamie Madill5b772312018-03-08 20:28:32 -05005011bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005012 GLuint attribIndex,
5013 GLint size,
5014 GLenum type,
5015 GLboolean pureInteger)
5016{
5017 const Caps &caps = context->getCaps();
5018 if (attribIndex >= caps.maxVertexAttributes)
5019 {
Jamie Madille0472f32018-11-27 16:32:45 -05005020 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005021 return false;
5022 }
5023
5024 if (size < 1 || size > 4)
5025 {
Jamie Madille0472f32018-11-27 16:32:45 -05005026 context->validationError(GL_INVALID_VALUE, kInvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005027 return false;
Shao80957d92017-02-20 21:25:59 +08005028 }
5029
5030 switch (type)
5031 {
5032 case GL_BYTE:
5033 case GL_UNSIGNED_BYTE:
5034 case GL_SHORT:
5035 case GL_UNSIGNED_SHORT:
5036 break;
5037
5038 case GL_INT:
5039 case GL_UNSIGNED_INT:
5040 if (context->getClientMajorVersion() < 3)
5041 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005042 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005043 return false;
5044 }
5045 break;
5046
5047 case GL_FIXED:
5048 case GL_FLOAT:
5049 if (pureInteger)
5050 {
Jamie Madille0472f32018-11-27 16:32:45 -05005051 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005052 return false;
5053 }
5054 break;
5055
5056 case GL_HALF_FLOAT:
5057 if (context->getClientMajorVersion() < 3)
5058 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005059 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005060 return false;
5061 }
5062 if (pureInteger)
5063 {
Jamie Madille0472f32018-11-27 16:32:45 -05005064 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005065 return false;
5066 }
5067 break;
5068
5069 case GL_INT_2_10_10_10_REV:
5070 case GL_UNSIGNED_INT_2_10_10_10_REV:
5071 if (context->getClientMajorVersion() < 3)
5072 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005073 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005074 return false;
5075 }
5076 if (pureInteger)
5077 {
Jamie Madille0472f32018-11-27 16:32:45 -05005078 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005079 return false;
5080 }
5081 if (size != 4)
5082 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005083 context->validationError(GL_INVALID_OPERATION, kInvalidVertexAttribSize2101010);
Shao80957d92017-02-20 21:25:59 +08005084 return false;
5085 }
5086 break;
5087
5088 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005089 context->validationError(GL_INVALID_ENUM, kInvalidType);
Shao80957d92017-02-20 21:25:59 +08005090 return false;
5091 }
5092
5093 return true;
5094}
5095
Geoff Lang76e65652017-03-27 14:58:02 -04005096// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5097// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5098// specified clear value and the type of a buffer that is being cleared generates an
5099// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005100bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005101 GLint drawbuffer,
5102 const GLenum *validComponentTypes,
5103 size_t validComponentTypeCount)
5104{
5105 const FramebufferAttachment *attachment =
5106 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5107 if (attachment)
5108 {
5109 GLenum componentType = attachment->getFormat().info->componentType;
5110 const GLenum *end = validComponentTypes + validComponentTypeCount;
5111 if (std::find(validComponentTypes, end, componentType) == end)
5112 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005113 context->validationError(GL_INVALID_OPERATION, kNoDefinedClearConversion);
Geoff Lang76e65652017-03-27 14:58:02 -04005114 return false;
5115 }
5116 }
5117
5118 return true;
5119}
5120
Jamie Madill5b772312018-03-08 20:28:32 -05005121bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005122{
5123 if (!ValidateRobustEntryPoint(context, dataSize))
5124 {
5125 return false;
5126 }
5127
Jamie Madill43da7c42018-08-01 11:34:49 -04005128 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005129 if (pixelUnpackBuffer == nullptr)
5130 {
5131 if (dataSize < imageSize)
5132 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005133 context->validationError(GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
Corentin Wallezb2931602017-04-11 15:58:57 -04005134 }
5135 }
5136 return true;
5137}
5138
Jamie Madill5b772312018-03-08 20:28:32 -05005139bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005140 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005141 GLenum pname,
5142 bool pointerVersion,
5143 GLsizei *numParams)
5144{
5145 if (numParams)
5146 {
5147 *numParams = 0;
5148 }
5149
Corentin Walleze4477002017-12-01 14:39:58 -05005150 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005151 {
Jamie Madille0472f32018-11-27 16:32:45 -05005152 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005153 return false;
5154 }
5155
5156 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5157 if (!buffer)
5158 {
5159 // A null buffer means that "0" is bound to the requested buffer target
Jamie Madille0472f32018-11-27 16:32:45 -05005160 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005161 return false;
5162 }
5163
5164 const Extensions &extensions = context->getExtensions();
5165
5166 switch (pname)
5167 {
5168 case GL_BUFFER_USAGE:
5169 case GL_BUFFER_SIZE:
5170 break;
5171
5172 case GL_BUFFER_ACCESS_OES:
5173 if (!extensions.mapBuffer)
5174 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005175 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005176 return false;
5177 }
5178 break;
5179
5180 case GL_BUFFER_MAPPED:
5181 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5182 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5183 !extensions.mapBufferRange)
5184 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005185 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005186 return false;
5187 }
5188 break;
5189
5190 case GL_BUFFER_MAP_POINTER:
5191 if (!pointerVersion)
5192 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005193 context->validationError(GL_INVALID_ENUM, kInvalidMapPointerQuery);
Jamie Madillbe849e42017-05-02 15:49:00 -04005194 return false;
5195 }
5196 break;
5197
5198 case GL_BUFFER_ACCESS_FLAGS:
5199 case GL_BUFFER_MAP_OFFSET:
5200 case GL_BUFFER_MAP_LENGTH:
5201 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5202 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005203 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005204 return false;
5205 }
5206 break;
5207
Geoff Lang79b91402018-10-04 15:11:30 -04005208 case GL_MEMORY_SIZE_ANGLE:
5209 if (!context->getExtensions().memorySize)
5210 {
Jamie Madille0472f32018-11-27 16:32:45 -05005211 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Geoff Lang79b91402018-10-04 15:11:30 -04005212 return false;
5213 }
5214 break;
5215
Jamie Madillbe849e42017-05-02 15:49:00 -04005216 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005217 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005218 return false;
5219 }
5220
5221 // All buffer parameter queries return one value.
5222 if (numParams)
5223 {
5224 *numParams = 1;
5225 }
5226
5227 return true;
5228}
5229
5230bool ValidateGetRenderbufferParameterivBase(Context *context,
5231 GLenum target,
5232 GLenum pname,
5233 GLsizei *length)
5234{
5235 if (length)
5236 {
5237 *length = 0;
5238 }
5239
5240 if (target != GL_RENDERBUFFER)
5241 {
Jamie Madille0472f32018-11-27 16:32:45 -05005242 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005243 return false;
5244 }
5245
5246 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5247 if (renderbuffer == nullptr)
5248 {
Jamie Madille0472f32018-11-27 16:32:45 -05005249 context->validationError(GL_INVALID_OPERATION, kRenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005250 return false;
5251 }
5252
5253 switch (pname)
5254 {
5255 case GL_RENDERBUFFER_WIDTH:
5256 case GL_RENDERBUFFER_HEIGHT:
5257 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5258 case GL_RENDERBUFFER_RED_SIZE:
5259 case GL_RENDERBUFFER_GREEN_SIZE:
5260 case GL_RENDERBUFFER_BLUE_SIZE:
5261 case GL_RENDERBUFFER_ALPHA_SIZE:
5262 case GL_RENDERBUFFER_DEPTH_SIZE:
5263 case GL_RENDERBUFFER_STENCIL_SIZE:
5264 break;
5265
5266 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5267 if (!context->getExtensions().framebufferMultisample)
5268 {
Jamie Madille0472f32018-11-27 16:32:45 -05005269 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272 break;
5273
Geoff Lang79b91402018-10-04 15:11:30 -04005274 case GL_MEMORY_SIZE_ANGLE:
5275 if (!context->getExtensions().memorySize)
5276 {
Jamie Madille0472f32018-11-27 16:32:45 -05005277 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Geoff Lang79b91402018-10-04 15:11:30 -04005278 return false;
5279 }
5280 break;
5281
Jamie Madillbe849e42017-05-02 15:49:00 -04005282 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005283 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005284 return false;
5285 }
5286
5287 if (length)
5288 {
5289 *length = 1;
5290 }
5291 return true;
5292}
5293
5294bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5295{
5296 if (length)
5297 {
5298 *length = 0;
5299 }
5300
5301 if (GetValidShader(context, shader) == nullptr)
5302 {
5303 return false;
5304 }
5305
5306 switch (pname)
5307 {
5308 case GL_SHADER_TYPE:
5309 case GL_DELETE_STATUS:
5310 case GL_COMPILE_STATUS:
5311 case GL_INFO_LOG_LENGTH:
5312 case GL_SHADER_SOURCE_LENGTH:
5313 break;
5314
5315 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5316 if (!context->getExtensions().translatedShaderSource)
5317 {
Jamie Madille0472f32018-11-27 16:32:45 -05005318 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005319 return false;
5320 }
5321 break;
5322
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005323 case GL_COMPLETION_STATUS_KHR:
5324 if (!context->getExtensions().parallelShaderCompile)
5325 {
Jamie Madille0472f32018-11-27 16:32:45 -05005326 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005327 return false;
5328 }
5329 break;
5330
Jamie Madillbe849e42017-05-02 15:49:00 -04005331 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005332 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005333 return false;
5334 }
5335
5336 if (length)
5337 {
5338 *length = 1;
5339 }
5340 return true;
5341}
5342
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005343bool ValidateGetTexParameterBase(Context *context,
5344 TextureType target,
5345 GLenum pname,
5346 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005347{
5348 if (length)
5349 {
5350 *length = 0;
5351 }
5352
5353 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5354 {
Jamie Madille0472f32018-11-27 16:32:45 -05005355 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005356 return false;
5357 }
5358
5359 if (context->getTargetTexture(target) == nullptr)
5360 {
5361 // Should only be possible for external textures
Jamie Madille0472f32018-11-27 16:32:45 -05005362 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005363 return false;
5364 }
5365
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005366 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5367 {
Jamie Madille0472f32018-11-27 16:32:45 -05005368 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005369 return false;
5370 }
5371
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 switch (pname)
5373 {
5374 case GL_TEXTURE_MAG_FILTER:
5375 case GL_TEXTURE_MIN_FILTER:
5376 case GL_TEXTURE_WRAP_S:
5377 case GL_TEXTURE_WRAP_T:
5378 break;
5379
5380 case GL_TEXTURE_USAGE_ANGLE:
5381 if (!context->getExtensions().textureUsage)
5382 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005383 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005384 return false;
5385 }
5386 break;
5387
5388 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005389 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005390 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005391 return false;
5392 }
5393 break;
5394
5395 case GL_TEXTURE_IMMUTABLE_FORMAT:
5396 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5397 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005398 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005399 return false;
5400 }
5401 break;
5402
5403 case GL_TEXTURE_WRAP_R:
5404 case GL_TEXTURE_IMMUTABLE_LEVELS:
5405 case GL_TEXTURE_SWIZZLE_R:
5406 case GL_TEXTURE_SWIZZLE_G:
5407 case GL_TEXTURE_SWIZZLE_B:
5408 case GL_TEXTURE_SWIZZLE_A:
5409 case GL_TEXTURE_BASE_LEVEL:
5410 case GL_TEXTURE_MAX_LEVEL:
5411 case GL_TEXTURE_MIN_LOD:
5412 case GL_TEXTURE_MAX_LOD:
5413 case GL_TEXTURE_COMPARE_MODE:
5414 case GL_TEXTURE_COMPARE_FUNC:
5415 if (context->getClientMajorVersion() < 3)
5416 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005417 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Jamie Madillbe849e42017-05-02 15:49:00 -04005418 return false;
5419 }
5420 break;
5421
5422 case GL_TEXTURE_SRGB_DECODE_EXT:
5423 if (!context->getExtensions().textureSRGBDecode)
5424 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005425 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005426 return false;
5427 }
5428 break;
5429
Yunchao Hebacaa712018-01-30 14:01:39 +08005430 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5431 if (context->getClientVersion() < Version(3, 1))
5432 {
Jamie Madille0472f32018-11-27 16:32:45 -05005433 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Yunchao Hebacaa712018-01-30 14:01:39 +08005434 return false;
5435 }
5436 break;
5437
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005438 case GL_GENERATE_MIPMAP:
5439 case GL_TEXTURE_CROP_RECT_OES:
5440 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5441 // after GL_OES_draw_texture functionality implemented
5442 if (context->getClientMajorVersion() > 1)
5443 {
Jamie Madille0472f32018-11-27 16:32:45 -05005444 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005445 return false;
5446 }
5447 break;
Geoff Lang79b91402018-10-04 15:11:30 -04005448
5449 case GL_MEMORY_SIZE_ANGLE:
5450 if (!context->getExtensions().memorySize)
5451 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005452 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang79b91402018-10-04 15:11:30 -04005453 return false;
5454 }
5455 break;
5456
Till Rathmannb8543632018-10-02 19:46:14 +02005457 case GL_TEXTURE_BORDER_COLOR:
5458 if (!context->getExtensions().textureBorderClamp)
5459 {
Jamie Madille0472f32018-11-27 16:32:45 -05005460 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02005461 return false;
5462 }
5463 break;
5464
Jamie Madillbe849e42017-05-02 15:49:00 -04005465 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005466 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 return false;
5468 }
5469
5470 if (length)
5471 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005472 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005473 }
5474 return true;
5475}
5476
5477bool ValidateGetVertexAttribBase(Context *context,
5478 GLuint index,
5479 GLenum pname,
5480 GLsizei *length,
5481 bool pointer,
5482 bool pureIntegerEntryPoint)
5483{
5484 if (length)
5485 {
5486 *length = 0;
5487 }
5488
5489 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5490 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005491 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 return false;
5493 }
5494
5495 if (index >= context->getCaps().maxVertexAttributes)
5496 {
Jamie Madille0472f32018-11-27 16:32:45 -05005497 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005498 return false;
5499 }
5500
5501 if (pointer)
5502 {
5503 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5504 {
Jamie Madille0472f32018-11-27 16:32:45 -05005505 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005506 return false;
5507 }
5508 }
5509 else
5510 {
5511 switch (pname)
5512 {
5513 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5514 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5515 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5516 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5517 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5518 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5519 case GL_CURRENT_VERTEX_ATTRIB:
5520 break;
5521
5522 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5523 static_assert(
5524 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5525 "ANGLE extension enums not equal to GL enums.");
5526 if (context->getClientMajorVersion() < 3 &&
5527 !context->getExtensions().instancedArrays)
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_ARRAY_INTEGER:
5535 if (context->getClientMajorVersion() < 3)
5536 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005537 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005538 return false;
5539 }
5540 break;
5541
5542 case GL_VERTEX_ATTRIB_BINDING:
5543 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5544 if (context->getClientVersion() < ES_3_1)
5545 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005546 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005547 return false;
5548 }
5549 break;
5550
5551 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005552 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005553 return false;
5554 }
5555 }
5556
5557 if (length)
5558 {
5559 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5560 {
5561 *length = 4;
5562 }
5563 else
5564 {
5565 *length = 1;
5566 }
5567 }
5568
5569 return true;
5570}
5571
Jamie Madill4928b7c2017-06-20 12:57:39 -04005572bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005573 GLint x,
5574 GLint y,
5575 GLsizei width,
5576 GLsizei height,
5577 GLenum format,
5578 GLenum type,
5579 GLsizei bufSize,
5580 GLsizei *length,
5581 GLsizei *columns,
5582 GLsizei *rows,
5583 void *pixels)
5584{
5585 if (length != nullptr)
5586 {
5587 *length = 0;
5588 }
5589 if (rows != nullptr)
5590 {
5591 *rows = 0;
5592 }
5593 if (columns != nullptr)
5594 {
5595 *columns = 0;
5596 }
5597
5598 if (width < 0 || height < 0)
5599 {
Jamie Madille0472f32018-11-27 16:32:45 -05005600 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005601 return false;
5602 }
5603
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005604 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005605
Jamie Madill427064d2018-04-13 16:20:34 -04005606 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005607 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005608 return false;
5609 }
5610
Jamie Madille98b1b52018-03-08 09:47:23 -05005611 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005612 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005613 return false;
5614 }
5615
Jamie Madill690c8eb2018-03-12 15:20:03 -04005616 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005617 ASSERT(framebuffer);
5618
5619 if (framebuffer->getReadBufferState() == GL_NONE)
5620 {
Jamie Madille0472f32018-11-27 16:32:45 -05005621 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005622 return false;
5623 }
5624
5625 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5626 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5627 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5628 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5629 // situation is an application error that would lead to a crash in ANGLE.
5630 if (readBuffer == nullptr)
5631 {
Jamie Madille0472f32018-11-27 16:32:45 -05005632 context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005633 return false;
5634 }
5635
Martin Radev28031682017-07-28 14:47:56 +03005636 // ANGLE_multiview, Revision 1:
5637 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005638 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5639 // in the current read framebuffer is more than one.
5640 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005641 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005642 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
Martin Radev28031682017-07-28 14:47:56 +03005643 return false;
5644 }
5645
Geoff Lang280ba992017-04-18 16:30:58 -04005646 if (context->getExtensions().webglCompatibility)
5647 {
5648 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5649 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5650 // and type before validating the combination of format and type. However, the
5651 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5652 // verifies that GL_INVALID_OPERATION is generated.
5653 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5654 // dEQP/WebGL.
5655 if (!ValidReadPixelsFormatEnum(context, format))
5656 {
Jamie Madille0472f32018-11-27 16:32:45 -05005657 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005658 return false;
5659 }
5660
5661 if (!ValidReadPixelsTypeEnum(context, type))
5662 {
Jamie Madille0472f32018-11-27 16:32:45 -05005663 context->validationError(GL_INVALID_ENUM, kInvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005664 return false;
5665 }
5666 }
5667
Jamie Madill690c8eb2018-03-12 15:20:03 -04005668 GLenum currentFormat = GL_NONE;
5669 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5670
5671 GLenum currentType = GL_NONE;
5672 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5673
Jamie Madillbe849e42017-05-02 15:49:00 -04005674 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5675
5676 bool validFormatTypeCombination =
5677 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5678
5679 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5680 {
Jamie Madille0472f32018-11-27 16:32:45 -05005681 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005682 return false;
5683 }
5684
5685 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005686 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005687 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5688 {
5689 // ...the buffer object's data store is currently mapped.
Jamie Madillc3e37312018-11-30 15:25:39 -05005690 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
Jamie Madillbe849e42017-05-02 15:49:00 -04005691 return false;
5692 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005693 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5694 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5695 {
Jamie Madille0472f32018-11-27 16:32:45 -05005696 context->validationError(GL_INVALID_OPERATION, kPixelPackBufferBoundForTransformFeedback);
James Darpiniane8a93c62018-01-04 18:02:24 -08005697 return false;
5698 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005699
5700 // .. the data would be packed to the buffer object such that the memory writes required
5701 // would exceed the data store size.
5702 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005703 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005704 const auto &pack = context->getGLState().getPackState();
5705
Jamie Madillca2ff382018-07-11 09:01:17 -04005706 GLuint endByte = 0;
5707 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005708 {
Jamie Madille0472f32018-11-27 16:32:45 -05005709 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005710 return false;
5711 }
5712
Jamie Madillbe849e42017-05-02 15:49:00 -04005713 if (bufSize >= 0)
5714 {
5715 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5716 {
Jamie Madille0472f32018-11-27 16:32:45 -05005717 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005718 return false;
5719 }
5720 }
5721
5722 if (pixelPackBuffer != nullptr)
5723 {
5724 CheckedNumeric<size_t> checkedEndByte(endByte);
5725 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5726 checkedEndByte += checkedOffset;
5727
5728 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5729 {
5730 // Overflow past the end of the buffer
Jamie Madille0472f32018-11-27 16:32:45 -05005731 context->validationError(GL_INVALID_OPERATION, kParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005732 return false;
5733 }
5734 }
5735
5736 if (pixelPackBuffer == nullptr && length != nullptr)
5737 {
5738 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5739 {
Jamie Madille0472f32018-11-27 16:32:45 -05005740 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005741 return false;
5742 }
5743
5744 *length = static_cast<GLsizei>(endByte);
5745 }
5746
Geoff Langa953b522018-02-21 16:56:23 -05005747 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005748 angle::CheckedNumeric<int> clippedExtent(length);
5749 if (start < 0)
5750 {
5751 // "subtract" the area that is less than 0
5752 clippedExtent += start;
5753 }
5754
Geoff Langa953b522018-02-21 16:56:23 -05005755 angle::CheckedNumeric<int> readExtent = start;
5756 readExtent += length;
5757 if (!readExtent.IsValid())
5758 {
5759 return false;
5760 }
5761
5762 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005763 {
5764 // Subtract the region to the right of the read buffer
5765 clippedExtent -= (readExtent - bufferSize);
5766 }
5767
5768 if (!clippedExtent.IsValid())
5769 {
Geoff Langa953b522018-02-21 16:56:23 -05005770 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005771 }
5772
Geoff Langa953b522018-02-21 16:56:23 -05005773 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5774 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005775 };
5776
Geoff Langa953b522018-02-21 16:56:23 -05005777 GLsizei writtenColumns = 0;
5778 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5779 {
Jamie Madille0472f32018-11-27 16:32:45 -05005780 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langa953b522018-02-21 16:56:23 -05005781 return false;
5782 }
5783
5784 GLsizei writtenRows = 0;
5785 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5786 {
Jamie Madille0472f32018-11-27 16:32:45 -05005787 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langa953b522018-02-21 16:56:23 -05005788 return false;
5789 }
5790
Jamie Madillbe849e42017-05-02 15:49:00 -04005791 if (columns != nullptr)
5792 {
Geoff Langa953b522018-02-21 16:56:23 -05005793 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005794 }
5795
5796 if (rows != nullptr)
5797 {
Geoff Langa953b522018-02-21 16:56:23 -05005798 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005799 }
5800
5801 return true;
5802}
5803
5804template <typename ParamType>
5805bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005806 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 GLenum pname,
5808 GLsizei bufSize,
Till Rathmannb8543632018-10-02 19:46:14 +02005809 bool vectorParams,
Jamie Madillbe849e42017-05-02 15:49:00 -04005810 const ParamType *params)
5811{
5812 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5813 {
Jamie Madille0472f32018-11-27 16:32:45 -05005814 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 return false;
5816 }
5817
5818 if (context->getTargetTexture(target) == nullptr)
5819 {
5820 // Should only be possible for external textures
Jamie Madille0472f32018-11-27 16:32:45 -05005821 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005822 return false;
5823 }
5824
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005825 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005826 if (bufSize >= 0 && bufSize < minBufSize)
5827 {
Jamie Madille0472f32018-11-27 16:32:45 -05005828 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005829 return false;
5830 }
5831
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005832 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5833 {
Jamie Madille0472f32018-11-27 16:32:45 -05005834 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005835 return false;
5836 }
5837
Jamie Madillbe849e42017-05-02 15:49:00 -04005838 switch (pname)
5839 {
5840 case GL_TEXTURE_WRAP_R:
5841 case GL_TEXTURE_SWIZZLE_R:
5842 case GL_TEXTURE_SWIZZLE_G:
5843 case GL_TEXTURE_SWIZZLE_B:
5844 case GL_TEXTURE_SWIZZLE_A:
5845 case GL_TEXTURE_BASE_LEVEL:
5846 case GL_TEXTURE_MAX_LEVEL:
5847 case GL_TEXTURE_COMPARE_MODE:
5848 case GL_TEXTURE_COMPARE_FUNC:
5849 case GL_TEXTURE_MIN_LOD:
5850 case GL_TEXTURE_MAX_LOD:
5851 if (context->getClientMajorVersion() < 3)
5852 {
Jamie Madille0472f32018-11-27 16:32:45 -05005853 context->validationError(GL_INVALID_ENUM, kES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005854 return false;
5855 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005856 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005857 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005858 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005859 return false;
5860 }
5861 break;
5862
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005863 case GL_GENERATE_MIPMAP:
5864 case GL_TEXTURE_CROP_RECT_OES:
5865 if (context->getClientMajorVersion() > 1)
5866 {
Jamie Madille0472f32018-11-27 16:32:45 -05005867 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005868 return false;
5869 }
5870 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005871 default:
5872 break;
5873 }
5874
Olli Etuahod310a432018-08-24 15:40:23 +03005875 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005876 {
5877 switch (pname)
5878 {
5879 case GL_TEXTURE_MIN_FILTER:
5880 case GL_TEXTURE_MAG_FILTER:
5881 case GL_TEXTURE_WRAP_S:
5882 case GL_TEXTURE_WRAP_T:
5883 case GL_TEXTURE_WRAP_R:
5884 case GL_TEXTURE_MIN_LOD:
5885 case GL_TEXTURE_MAX_LOD:
5886 case GL_TEXTURE_COMPARE_MODE:
5887 case GL_TEXTURE_COMPARE_FUNC:
Till Rathmannb8543632018-10-02 19:46:14 +02005888 case GL_TEXTURE_BORDER_COLOR:
Jamie Madillc3e37312018-11-30 15:25:39 -05005889 context->validationError(GL_INVALID_ENUM, kInvalidPname);
JiangYizhou4cff8d62017-07-06 14:54:09 +08005890 return false;
5891 }
5892 }
5893
Jamie Madillbe849e42017-05-02 15:49:00 -04005894 switch (pname)
5895 {
5896 case GL_TEXTURE_WRAP_S:
5897 case GL_TEXTURE_WRAP_T:
5898 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005899 {
5900 bool restrictedWrapModes =
5901 target == TextureType::External || target == TextureType::Rectangle;
5902 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005903 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005904 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005905 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005906 }
5907 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005908
5909 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005910 {
5911 bool restrictedMinFilter =
5912 target == TextureType::External || target == TextureType::Rectangle;
5913 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005914 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005915 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005916 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005917 }
5918 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005919
5920 case GL_TEXTURE_MAG_FILTER:
5921 if (!ValidateTextureMagFilterValue(context, params))
5922 {
5923 return false;
5924 }
5925 break;
5926
5927 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005928 if (!context->getExtensions().textureUsage)
5929 {
Jamie Madille0472f32018-11-27 16:32:45 -05005930 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang91ab54b2017-10-30 15:12:42 -04005931 return false;
5932 }
5933
Jamie Madillbe849e42017-05-02 15:49:00 -04005934 switch (ConvertToGLenum(params[0]))
5935 {
5936 case GL_NONE:
5937 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5938 break;
5939
5940 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005941 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005942 return false;
5943 }
5944 break;
5945
5946 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005947 {
5948 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5949 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005950 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005951 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005952 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005953 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5954 }
5955 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005956
5957 case GL_TEXTURE_MIN_LOD:
5958 case GL_TEXTURE_MAX_LOD:
5959 // any value is permissible
5960 break;
5961
5962 case GL_TEXTURE_COMPARE_MODE:
5963 if (!ValidateTextureCompareModeValue(context, params))
5964 {
5965 return false;
5966 }
5967 break;
5968
5969 case GL_TEXTURE_COMPARE_FUNC:
5970 if (!ValidateTextureCompareFuncValue(context, params))
5971 {
5972 return false;
5973 }
5974 break;
5975
5976 case GL_TEXTURE_SWIZZLE_R:
5977 case GL_TEXTURE_SWIZZLE_G:
5978 case GL_TEXTURE_SWIZZLE_B:
5979 case GL_TEXTURE_SWIZZLE_A:
5980 switch (ConvertToGLenum(params[0]))
5981 {
5982 case GL_RED:
5983 case GL_GREEN:
5984 case GL_BLUE:
5985 case GL_ALPHA:
5986 case GL_ZERO:
5987 case GL_ONE:
5988 break;
5989
5990 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005991 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005992 return false;
5993 }
5994 break;
5995
5996 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005997 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005998 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005999 context->validationError(GL_INVALID_VALUE, kBaseLevelNegative);
Jamie Madillbe849e42017-05-02 15:49:00 -04006000 return false;
6001 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006002 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006003 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006004 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04006005 return false;
6006 }
Olli Etuahod310a432018-08-24 15:40:23 +03006007 if ((target == TextureType::_2DMultisample ||
6008 target == TextureType::_2DMultisampleArray) &&
6009 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006010 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006011 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
JiangYizhou4cff8d62017-07-06 14:54:09 +08006012 return false;
6013 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006014 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006015 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006016 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006017 return false;
6018 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006019 break;
6020
6021 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006022 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006023 {
Jamie Madille0472f32018-11-27 16:32:45 -05006024 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006025 return false;
6026 }
6027 break;
6028
6029 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6030 if (context->getClientVersion() < Version(3, 1))
6031 {
Jamie Madille0472f32018-11-27 16:32:45 -05006032 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006033 return false;
6034 }
6035 switch (ConvertToGLenum(params[0]))
6036 {
6037 case GL_DEPTH_COMPONENT:
6038 case GL_STENCIL_INDEX:
6039 break;
6040
6041 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006042 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006043 return false;
6044 }
6045 break;
6046
6047 case GL_TEXTURE_SRGB_DECODE_EXT:
6048 if (!ValidateTextureSRGBDecodeValue(context, params))
6049 {
6050 return false;
6051 }
6052 break;
6053
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006054 case GL_GENERATE_MIPMAP:
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006055 if (context->getClientMajorVersion() > 1)
6056 {
Jamie Madille0472f32018-11-27 16:32:45 -05006057 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006058 return false;
6059 }
6060 break;
Till Rathmannb8543632018-10-02 19:46:14 +02006061
6062 case GL_TEXTURE_CROP_RECT_OES:
6063 if (context->getClientMajorVersion() > 1)
6064 {
Jamie Madille0472f32018-11-27 16:32:45 -05006065 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Till Rathmannb8543632018-10-02 19:46:14 +02006066 return false;
6067 }
6068 if (!vectorParams)
6069 {
Jamie Madille0472f32018-11-27 16:32:45 -05006070 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006071 return false;
6072 }
6073 break;
6074
6075 case GL_TEXTURE_BORDER_COLOR:
6076 if (!context->getExtensions().textureBorderClamp)
6077 {
Jamie Madille0472f32018-11-27 16:32:45 -05006078 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006079 return false;
6080 }
6081 if (!vectorParams)
6082 {
Jamie Madille0472f32018-11-27 16:32:45 -05006083 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006084 return false;
6085 }
6086 break;
6087
Jamie Madillbe849e42017-05-02 15:49:00 -04006088 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006089 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006090 return false;
6091 }
6092
6093 return true;
6094}
6095
Till Rathmannb8543632018-10-02 19:46:14 +02006096template bool ValidateTexParameterBase(Context *,
6097 TextureType,
6098 GLenum,
6099 GLsizei,
6100 bool,
6101 const GLfloat *);
6102template bool ValidateTexParameterBase(Context *,
6103 TextureType,
6104 GLenum,
6105 GLsizei,
6106 bool,
6107 const GLint *);
6108template bool ValidateTexParameterBase(Context *,
6109 TextureType,
6110 GLenum,
6111 GLsizei,
6112 bool,
6113 const GLuint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006114
Jamie Madill5b772312018-03-08 20:28:32 -05006115bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006116{
6117 if (index >= MAX_VERTEX_ATTRIBS)
6118 {
Jamie Madille0472f32018-11-27 16:32:45 -05006119 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Jamie Madill12e957f2017-08-26 21:42:26 -04006120 return false;
6121 }
6122
6123 return true;
6124}
6125
6126bool ValidateGetActiveUniformBlockivBase(Context *context,
6127 GLuint program,
6128 GLuint uniformBlockIndex,
6129 GLenum pname,
6130 GLsizei *length)
6131{
6132 if (length)
6133 {
6134 *length = 0;
6135 }
6136
6137 if (context->getClientMajorVersion() < 3)
6138 {
Jamie Madille0472f32018-11-27 16:32:45 -05006139 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill12e957f2017-08-26 21:42:26 -04006140 return false;
6141 }
6142
6143 Program *programObject = GetValidProgram(context, program);
6144 if (!programObject)
6145 {
6146 return false;
6147 }
6148
6149 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6150 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006151 context->validationError(GL_INVALID_VALUE, kIndexExceedsActiveUniformBlockCount);
Jamie Madill12e957f2017-08-26 21:42:26 -04006152 return false;
6153 }
6154
6155 switch (pname)
6156 {
6157 case GL_UNIFORM_BLOCK_BINDING:
6158 case GL_UNIFORM_BLOCK_DATA_SIZE:
6159 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6160 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6161 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6162 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6163 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6164 break;
6165
6166 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006167 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill12e957f2017-08-26 21:42:26 -04006168 return false;
6169 }
6170
6171 if (length)
6172 {
6173 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6174 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006175 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006176 programObject->getUniformBlockByIndex(uniformBlockIndex);
6177 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6178 }
6179 else
6180 {
6181 *length = 1;
6182 }
6183 }
6184
6185 return true;
6186}
6187
Jamie Madill9696d072017-08-26 23:19:57 -04006188template <typename ParamType>
6189bool ValidateSamplerParameterBase(Context *context,
6190 GLuint sampler,
6191 GLenum pname,
6192 GLsizei bufSize,
Till Rathmannb8543632018-10-02 19:46:14 +02006193 bool vectorParams,
Jamie Madill9696d072017-08-26 23:19:57 -04006194 ParamType *params)
6195{
6196 if (context->getClientMajorVersion() < 3)
6197 {
Jamie Madille0472f32018-11-27 16:32:45 -05006198 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006199 return false;
6200 }
6201
6202 if (!context->isSampler(sampler))
6203 {
Jamie Madille0472f32018-11-27 16:32:45 -05006204 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
Jamie Madill9696d072017-08-26 23:19:57 -04006205 return false;
6206 }
6207
Till Rathmannb8543632018-10-02 19:46:14 +02006208 const GLsizei minBufSize = GetSamplerParameterCount(pname);
Jamie Madill9696d072017-08-26 23:19:57 -04006209 if (bufSize >= 0 && bufSize < minBufSize)
6210 {
Jamie Madille0472f32018-11-27 16:32:45 -05006211 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madill9696d072017-08-26 23:19:57 -04006212 return false;
6213 }
6214
6215 switch (pname)
6216 {
6217 case GL_TEXTURE_WRAP_S:
6218 case GL_TEXTURE_WRAP_T:
6219 case GL_TEXTURE_WRAP_R:
6220 if (!ValidateTextureWrapModeValue(context, params, false))
6221 {
6222 return false;
6223 }
6224 break;
6225
6226 case GL_TEXTURE_MIN_FILTER:
6227 if (!ValidateTextureMinFilterValue(context, params, false))
6228 {
6229 return false;
6230 }
6231 break;
6232
6233 case GL_TEXTURE_MAG_FILTER:
6234 if (!ValidateTextureMagFilterValue(context, params))
6235 {
6236 return false;
6237 }
6238 break;
6239
6240 case GL_TEXTURE_MIN_LOD:
6241 case GL_TEXTURE_MAX_LOD:
6242 // any value is permissible
6243 break;
6244
6245 case GL_TEXTURE_COMPARE_MODE:
6246 if (!ValidateTextureCompareModeValue(context, params))
6247 {
6248 return false;
6249 }
6250 break;
6251
6252 case GL_TEXTURE_COMPARE_FUNC:
6253 if (!ValidateTextureCompareFuncValue(context, params))
6254 {
6255 return false;
6256 }
6257 break;
6258
6259 case GL_TEXTURE_SRGB_DECODE_EXT:
6260 if (!ValidateTextureSRGBDecodeValue(context, params))
6261 {
6262 return false;
6263 }
6264 break;
6265
Luc Ferron1b1a8642018-01-23 15:12:01 -05006266 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6267 {
6268 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6269 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6270 {
6271 return false;
6272 }
6273 }
6274 break;
6275
Till Rathmannb8543632018-10-02 19:46:14 +02006276 case GL_TEXTURE_BORDER_COLOR:
6277 if (!context->getExtensions().textureBorderClamp)
6278 {
Jamie Madille0472f32018-11-27 16:32:45 -05006279 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006280 return false;
6281 }
6282 if (!vectorParams)
6283 {
Jamie Madille0472f32018-11-27 16:32:45 -05006284 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006285 return false;
6286 }
6287 break;
6288
Jamie Madill9696d072017-08-26 23:19:57 -04006289 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006290 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006291 return false;
6292 }
6293
6294 return true;
6295}
6296
Till Rathmannb8543632018-10-02 19:46:14 +02006297template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, bool, GLfloat *);
6298template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, bool, GLint *);
6299template bool ValidateSamplerParameterBase(Context *,
6300 GLuint,
6301 GLenum,
6302 GLsizei,
6303 bool,
6304 const GLuint *);
Jamie Madill9696d072017-08-26 23:19:57 -04006305
6306bool ValidateGetSamplerParameterBase(Context *context,
6307 GLuint sampler,
6308 GLenum pname,
6309 GLsizei *length)
6310{
6311 if (length)
6312 {
6313 *length = 0;
6314 }
6315
6316 if (context->getClientMajorVersion() < 3)
6317 {
Jamie Madille0472f32018-11-27 16:32:45 -05006318 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006319 return false;
6320 }
6321
6322 if (!context->isSampler(sampler))
6323 {
Jamie Madille0472f32018-11-27 16:32:45 -05006324 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
Jamie Madill9696d072017-08-26 23:19:57 -04006325 return false;
6326 }
6327
6328 switch (pname)
6329 {
6330 case GL_TEXTURE_WRAP_S:
6331 case GL_TEXTURE_WRAP_T:
6332 case GL_TEXTURE_WRAP_R:
6333 case GL_TEXTURE_MIN_FILTER:
6334 case GL_TEXTURE_MAG_FILTER:
6335 case GL_TEXTURE_MIN_LOD:
6336 case GL_TEXTURE_MAX_LOD:
6337 case GL_TEXTURE_COMPARE_MODE:
6338 case GL_TEXTURE_COMPARE_FUNC:
6339 break;
6340
Luc Ferron1b1a8642018-01-23 15:12:01 -05006341 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6342 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6343 {
6344 return false;
6345 }
6346 break;
6347
Jamie Madill9696d072017-08-26 23:19:57 -04006348 case GL_TEXTURE_SRGB_DECODE_EXT:
6349 if (!context->getExtensions().textureSRGBDecode)
6350 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006351 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006352 return false;
6353 }
6354 break;
6355
Till Rathmannb8543632018-10-02 19:46:14 +02006356 case GL_TEXTURE_BORDER_COLOR:
6357 if (!context->getExtensions().textureBorderClamp)
6358 {
Jamie Madille0472f32018-11-27 16:32:45 -05006359 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006360 return false;
6361 }
6362 break;
6363
Jamie Madill9696d072017-08-26 23:19:57 -04006364 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006365 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006366 return false;
6367 }
6368
6369 if (length)
6370 {
Till Rathmannb8543632018-10-02 19:46:14 +02006371 *length = GetSamplerParameterCount(pname);
Jamie Madill9696d072017-08-26 23:19:57 -04006372 }
6373 return true;
6374}
6375
6376bool ValidateGetInternalFormativBase(Context *context,
6377 GLenum target,
6378 GLenum internalformat,
6379 GLenum pname,
6380 GLsizei bufSize,
6381 GLsizei *numParams)
6382{
6383 if (numParams)
6384 {
6385 *numParams = 0;
6386 }
6387
6388 if (context->getClientMajorVersion() < 3)
6389 {
Jamie Madille0472f32018-11-27 16:32:45 -05006390 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006391 return false;
6392 }
6393
6394 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006395 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006396 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006397 context->validationError(GL_INVALID_ENUM, kFormatNotRenderable);
Jamie Madill9696d072017-08-26 23:19:57 -04006398 return false;
6399 }
6400
6401 switch (target)
6402 {
6403 case GL_RENDERBUFFER:
6404 break;
6405
6406 case GL_TEXTURE_2D_MULTISAMPLE:
Yizhou Jiang7818a852018-09-06 15:02:04 +08006407 if (context->getClientVersion() < ES_3_1 &&
6408 !context->getExtensions().textureMultisample)
Jamie Madill9696d072017-08-26 23:19:57 -04006409 {
Jamie Madill610640f2018-11-21 17:28:41 -05006410 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05006411 kMultisampleTextureExtensionOrES31Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006412 return false;
6413 }
6414 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006415 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6416 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006417 {
Jamie Madille0472f32018-11-27 16:32:45 -05006418 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
Olli Etuahod310a432018-08-24 15:40:23 +03006419 return false;
6420 }
6421 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006422 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006423 context->validationError(GL_INVALID_ENUM, kInvalidTarget);
Jamie Madill9696d072017-08-26 23:19:57 -04006424 return false;
6425 }
6426
6427 if (bufSize < 0)
6428 {
Jamie Madille0472f32018-11-27 16:32:45 -05006429 context->validationError(GL_INVALID_VALUE, kInsufficientBufferSize);
Jamie Madill9696d072017-08-26 23:19:57 -04006430 return false;
6431 }
6432
6433 GLsizei maxWriteParams = 0;
6434 switch (pname)
6435 {
6436 case GL_NUM_SAMPLE_COUNTS:
6437 maxWriteParams = 1;
6438 break;
6439
6440 case GL_SAMPLES:
6441 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6442 break;
6443
6444 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006445 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006446 return false;
6447 }
6448
6449 if (numParams)
6450 {
6451 // glGetInternalFormativ will not overflow bufSize
6452 *numParams = std::min(bufSize, maxWriteParams);
6453 }
6454
6455 return true;
6456}
6457
Jamie Madille98b1b52018-03-08 09:47:23 -05006458bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6459{
Jamie Madill427064d2018-04-13 16:20:34 -04006460 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006461 {
Jamie Madille0472f32018-11-27 16:32:45 -05006462 context->validationError(GL_INVALID_OPERATION, kInvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006463 return false;
6464 }
6465 return true;
6466}
6467
Lingfeng Yang038dd532018-03-29 17:31:52 -07006468bool ValidateMultitextureUnit(Context *context, GLenum texture)
6469{
6470 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6471 {
Jamie Madille0472f32018-11-27 16:32:45 -05006472 context->validationError(GL_INVALID_ENUM, kInvalidMultitextureUnit);
Lingfeng Yang038dd532018-03-29 17:31:52 -07006473 return false;
6474 }
6475 return true;
6476}
6477
Olli Etuahod310a432018-08-24 15:40:23 +03006478bool ValidateTexStorageMultisample(Context *context,
6479 TextureType target,
6480 GLsizei samples,
6481 GLint internalFormat,
6482 GLsizei width,
6483 GLsizei height)
6484{
6485 const Caps &caps = context->getCaps();
6486 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6487 static_cast<GLuint>(height) > caps.max2DTextureSize)
6488 {
Jamie Madille0472f32018-11-27 16:32:45 -05006489 context->validationError(GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
Olli Etuahod310a432018-08-24 15:40:23 +03006490 return false;
6491 }
6492
6493 if (samples == 0)
6494 {
Jamie Madille0472f32018-11-27 16:32:45 -05006495 context->validationError(GL_INVALID_VALUE, kSamplesZero);
Olli Etuahod310a432018-08-24 15:40:23 +03006496 return false;
6497 }
6498
6499 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6500 if (!formatCaps.textureAttachment)
6501 {
Jamie Madille0472f32018-11-27 16:32:45 -05006502 context->validationError(GL_INVALID_ENUM, kRenderableInternalFormat);
Olli Etuahod310a432018-08-24 15:40:23 +03006503 return false;
6504 }
6505
6506 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6507 // is one of the unsized base internalformats listed in table 8.11.
6508 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6509 if (formatInfo.internalFormat == GL_NONE)
6510 {
Jamie Madille0472f32018-11-27 16:32:45 -05006511 context->validationError(GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
Olli Etuahod310a432018-08-24 15:40:23 +03006512 return false;
6513 }
6514
6515 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6516 {
Jamie Madille0472f32018-11-27 16:32:45 -05006517 context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
Olli Etuahod310a432018-08-24 15:40:23 +03006518 return false;
6519 }
6520
6521 Texture *texture = context->getTargetTexture(target);
6522 if (!texture || texture->id() == 0)
6523 {
Jamie Madille0472f32018-11-27 16:32:45 -05006524 context->validationError(GL_INVALID_OPERATION, kZeroBoundToTarget);
Olli Etuahod310a432018-08-24 15:40:23 +03006525 return false;
6526 }
6527
6528 if (texture->getImmutableFormat())
6529 {
Jamie Madille0472f32018-11-27 16:32:45 -05006530 context->validationError(GL_INVALID_OPERATION, kImmutableTextureBound);
Olli Etuahod310a432018-08-24 15:40:23 +03006531 return false;
6532 }
6533 return true;
6534}
6535
Yizhou Jiang7818a852018-09-06 15:02:04 +08006536bool ValidateTexStorage2DMultisampleBase(Context *context,
6537 TextureType target,
6538 GLsizei samples,
6539 GLint internalFormat,
6540 GLsizei width,
6541 GLsizei height)
6542{
6543 if (target != TextureType::_2DMultisample)
6544 {
Jamie Madille0472f32018-11-27 16:32:45 -05006545 context->validationError(GL_INVALID_ENUM, kInvalidTarget);
Yizhou Jiang7818a852018-09-06 15:02:04 +08006546 return false;
6547 }
6548
6549 if (width < 1 || height < 1)
6550 {
Jamie Madille0472f32018-11-27 16:32:45 -05006551 context->validationError(GL_INVALID_VALUE, kTextureSizeTooSmall);
Yizhou Jiang7818a852018-09-06 15:02:04 +08006552 return false;
6553 }
6554
6555 return ValidateTexStorageMultisample(context, target, samples, internalFormat, width, height);
6556}
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006557
6558bool ValidateGetTexLevelParameterBase(Context *context,
6559 TextureTarget target,
6560 GLint level,
6561 GLenum pname,
6562 GLsizei *length)
6563{
6564
6565 if (length)
6566 {
6567 *length = 0;
6568 }
6569
6570 TextureType type = TextureTargetToType(target);
6571
6572 if (!ValidTexLevelDestinationTarget(context, type))
6573 {
Jamie Madille0472f32018-11-27 16:32:45 -05006574 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006575 return false;
6576 }
6577
6578 if (context->getTargetTexture(type) == nullptr)
6579 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006580 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006581 return false;
6582 }
6583
6584 if (!ValidMipLevel(context, type, level))
6585 {
Jamie Madille0472f32018-11-27 16:32:45 -05006586 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006587 return false;
6588 }
6589
6590 switch (pname)
6591 {
6592 case GL_TEXTURE_RED_TYPE:
6593 case GL_TEXTURE_GREEN_TYPE:
6594 case GL_TEXTURE_BLUE_TYPE:
6595 case GL_TEXTURE_ALPHA_TYPE:
6596 case GL_TEXTURE_DEPTH_TYPE:
6597 break;
6598 case GL_TEXTURE_RED_SIZE:
6599 case GL_TEXTURE_GREEN_SIZE:
6600 case GL_TEXTURE_BLUE_SIZE:
6601 case GL_TEXTURE_ALPHA_SIZE:
6602 case GL_TEXTURE_DEPTH_SIZE:
6603 case GL_TEXTURE_STENCIL_SIZE:
6604 case GL_TEXTURE_SHARED_SIZE:
6605 break;
6606 case GL_TEXTURE_INTERNAL_FORMAT:
6607 case GL_TEXTURE_WIDTH:
6608 case GL_TEXTURE_HEIGHT:
6609 case GL_TEXTURE_DEPTH:
6610 break;
6611 case GL_TEXTURE_SAMPLES:
6612 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
6613 break;
6614 case GL_TEXTURE_COMPRESSED:
6615 break;
6616 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006617 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006618 return false;
6619 }
6620
6621 if (length)
6622 {
6623 *length = 1;
6624 }
6625 return true;
6626}
Yizhou Jiang7310da32018-11-05 14:40:01 +08006627
6628bool ValidateGetMultisamplefvBase(Context *context, GLenum pname, GLuint index, GLfloat *val)
6629{
6630 if (pname != GL_SAMPLE_POSITION)
6631 {
6632 context->validationError(GL_INVALID_ENUM, kInvalidPname);
6633 return false;
6634 }
6635
6636 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
6637 GLint samples = framebuffer->getSamples(context);
6638
6639 if (index >= static_cast<GLuint>(samples))
6640 {
6641 context->validationError(GL_INVALID_VALUE, kIndexExceedsSamples);
6642 return false;
6643 }
6644
6645 return true;
6646}
6647
6648bool ValidateSampleMaskiBase(Context *context, GLuint maskNumber, GLbitfield mask)
6649{
6650 if (maskNumber >= context->getCaps().maxSampleMaskWords)
6651 {
6652 context->validationError(GL_INVALID_VALUE, kInvalidSampleMaskNumber);
6653 return false;
6654 }
6655
6656 return true;
6657}
Jamie Madillc29968b2016-01-20 11:17:23 -05006658} // namespace gl