blob: 95653e585425bfa16bcddb95c9b202bdf61692a5 [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 Madillf5c88e72018-12-08 09:56:38 -05002929 // TODO(jmadill): Cache all of these into fast checks. http://anglebug.com/2966
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002930 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002931
Jamie Madill43da7c42018-08-01 11:34:49 -04002932 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002933 if (curTransformFeedback && curTransformFeedback->isActive() &&
2934 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002935 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002936 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2937 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
Jamie Madill9b025062018-12-12 15:44:12 -05002938 if (!context->getExtensions().geometryShader)
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002939 {
2940 // It is an invalid operation to call DrawElements, DrawRangeElements or
2941 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2942 // 86)
Jamie Madill610640f2018-11-21 17:28:41 -05002943 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05002944 kUnsupportedDrawModeForTransformFeedback);
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002945 return false;
2946 }
Jamie Madill9b025062018-12-12 15:44:12 -05002947
2948 // Note that we are missing overflow checks for the transform feedback buffers.
Jamie Madill250d33f2014-06-06 17:09:03 -04002949 }
2950
Jamie Madillf5c88e72018-12-08 09:56:38 -05002951 const VertexArray *vao = state.getVertexArray();
2952 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
2953
2954 if (elementArrayBuffer)
2955 {
2956 if (context->getExtensions().webglCompatibility)
2957 {
2958 if (elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
2959 {
2960 context->validationError(GL_INVALID_OPERATION,
2961 kElementArrayBufferBoundForTransformFeedback);
2962 return false;
2963 }
2964 }
2965 else if (elementArrayBuffer->isMapped())
2966 {
2967 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
2968 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the
2969 // WebGL 2.0 API. https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2970 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
2971 return false;
2972 }
2973 }
2974 else
2975 {
2976 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2977 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
2978 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
2979 if (!context->getGLState().areClientArraysEnabled() ||
2980 context->getExtensions().webglCompatibility)
2981 {
2982 context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
2983 return false;
2984 }
2985 }
2986
Jiajia Qind9671222016-11-29 16:30:31 +08002987 return true;
2988}
2989
Jamie Madill5b772312018-03-08 20:28:32 -05002990bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002991 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002992 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05002993 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04002994 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002995 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002996{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002997 if (!ValidateDrawElementsBase(context, mode, type))
Jamie Madillf5c88e72018-12-08 09:56:38 -05002998 {
Jiajia Qind9671222016-11-29 16:30:31 +08002999 return false;
Jamie Madillf5c88e72018-12-08 09:56:38 -05003000 }
Jiajia Qind9671222016-11-29 16:30:31 +08003001
Corentin Wallez170efbf2017-05-02 13:45:01 -04003002 if (!ValidateDrawBase(context, mode, count))
3003 {
3004 return false;
3005 }
3006
Jamie Madillf5c88e72018-12-08 09:56:38 -05003007 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04003008 const VertexArray *vao = state.getVertexArray();
Jamie Madillcd0a0a32018-10-18 18:41:57 -04003009 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003010
Jamie Madill8dc27f92018-11-29 11:45:44 -05003011 GLuint typeBytes = GetDrawElementsTypeSize(type);
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003012 ASSERT(isPow2(typeBytes) && typeBytes > 0);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003013
3014 if (context->getExtensions().webglCompatibility)
3015 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003016 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3017 {
3018 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3019 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3020 // data type passed to the call, or an INVALID_OPERATION error is generated.
Jamie Madille0472f32018-11-27 16:32:45 -05003021 context->validationError(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003022 return false;
3023 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003024
3025 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3026 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3027 // error is generated.
3028 if (reinterpret_cast<intptr_t>(indices) < 0)
3029 {
Jamie Madille0472f32018-11-27 16:32:45 -05003030 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003031 return false;
3032 }
Jamie Madillf5c88e72018-12-08 09:56:38 -05003033 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003034
Jamie Madillf5c88e72018-12-08 09:56:38 -05003035 // Early exit.
3036 if (count == 0)
3037 {
3038 return true;
3039 }
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003040
Jamie Madillf5c88e72018-12-08 09:56:38 -05003041 if (!elementArrayBuffer)
3042 {
3043 if (!indices)
James Darpiniane8a93c62018-01-04 18:02:24 -08003044 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003045 // This is an application error that would normally result in a crash, but we catch
3046 // it and return an error
3047 context->validationError(GL_INVALID_OPERATION, kElementArrayNoBufferOrPointer);
James Darpiniane8a93c62018-01-04 18:02:24 -08003048 return false;
3049 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003050 }
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003051 else
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003052 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003053 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3054 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3055 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3056 constexpr uint64_t kMaxTypeSize = 8;
3057 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3058 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3059 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3060
3061 uint64_t typeSize = typeBytes;
3062 uint64_t elementCount = static_cast<uint64_t>(count);
3063 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3064
3065 // Doing the multiplication here is overflow-safe
3066 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3067
3068 // The offset can be any value, check for overflows
3069 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3070 if (elementDataSizeNoOffset > kUint64Max - offset)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003071 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003072 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
3073 return false;
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003074 }
Jamie Madillf5c88e72018-12-08 09:56:38 -05003075
3076 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3077 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003078 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003079 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003080 return false;
3081 }
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003082 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003083
Jamie Madillf5c88e72018-12-08 09:56:38 -05003084 if (!context->getExtensions().robustBufferAccessBehavior && primcount > 0)
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003085 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003086 // Use the parameter buffer to retrieve and cache the index range.
3087 IndexRange indexRange;
3088 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
3089
3090 // If we use an index greater than our maximum supported index range, return an error.
3091 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
3092 // always return an error if possible here.
3093 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003094 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003095 context->validationError(GL_INVALID_OPERATION, kExceedsMaxElement);
3096 return false;
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003097 }
3098
Jamie Madillf5c88e72018-12-08 09:56:38 -05003099 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003100 {
Jamie Madillf5c88e72018-12-08 09:56:38 -05003101 return false;
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003102 }
Jamie Madillf5c88e72018-12-08 09:56:38 -05003103
3104 // No op if there are no real indices in the index data (all are primitive restart).
3105 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003106 }
3107
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003108 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003109}
3110
Jamie Madill5b772312018-03-08 20:28:32 -05003111bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003112 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003113 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05003114 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04003115 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003116 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003117{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003118 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003119}
3120
Geoff Lang3edfe032015-09-04 16:38:24 -04003121bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003122 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003123 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05003124 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04003125 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003126 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003127{
Geoff Lang63c5a592017-09-27 14:08:16 -04003128 if (!context->getExtensions().instancedArrays)
3129 {
Jamie Madille0472f32018-11-27 16:32:45 -05003130 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang63c5a592017-09-27 14:08:16 -04003131 return false;
3132 }
3133
Corentin Wallez170efbf2017-05-02 13:45:01 -04003134 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003135 {
3136 return false;
3137 }
3138
Corentin Wallez0dc97812017-06-22 14:38:44 -04003139 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003140}
3141
He Yunchaoced53ae2016-11-29 15:00:51 +08003142bool ValidateFramebufferTextureBase(Context *context,
3143 GLenum target,
3144 GLenum attachment,
3145 GLuint texture,
3146 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003147{
Geoff Lange8afa902017-09-27 15:00:43 -04003148 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003149 {
Jamie Madille0472f32018-11-27 16:32:45 -05003150 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003151 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003152 }
3153
3154 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003155 {
3156 return false;
3157 }
3158
Jamie Madill55ec3b12014-07-03 10:38:57 -04003159 if (texture != 0)
3160 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003161 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003162
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003163 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003164 {
Jamie Madille0472f32018-11-27 16:32:45 -05003165 context->validationError(GL_INVALID_OPERATION, kMissingTexture);
Geoff Langb1196682014-07-23 13:47:29 -04003166 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003167 }
3168
3169 if (level < 0)
3170 {
Jamie Madille0472f32018-11-27 16:32:45 -05003171 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04003172 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003173 }
3174 }
3175
Jamie Madill43da7c42018-08-01 11:34:49 -04003176 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003177 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003178
Jamie Madill84115c92015-04-23 15:00:07 -04003179 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003180 {
Jamie Madille0472f32018-11-27 16:32:45 -05003181 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003182 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003183 }
3184
3185 return true;
3186}
3187
Geoff Langb1196682014-07-23 13:47:29 -04003188bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003189{
3190 if (program == 0)
3191 {
Jamie Madille0472f32018-11-27 16:32:45 -05003192 context->validationError(GL_INVALID_VALUE, kProgramDoesNotExist);
Geoff Langb1196682014-07-23 13:47:29 -04003193 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003194 }
3195
Jamie Madill43da7c42018-08-01 11:34:49 -04003196 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003197 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003198 {
3199 return false;
3200 }
3201
Jamie Madill0063c512014-08-25 15:47:53 -04003202 if (!programObject || !programObject->isLinked())
3203 {
Jamie Madille0472f32018-11-27 16:32:45 -05003204 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003205 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003206 }
3207
Geoff Lang7dd2e102014-11-10 15:19:26 -05003208 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003209 {
Jamie Madille0472f32018-11-27 16:32:45 -05003210 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
Geoff Langb1196682014-07-23 13:47:29 -04003211 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003212 }
3213
Jamie Madill0063c512014-08-25 15:47:53 -04003214 return true;
3215}
3216
Geoff Langf41d0ee2016-10-07 13:04:23 -04003217static bool ValidateSizedGetUniform(Context *context,
3218 GLuint program,
3219 GLint location,
3220 GLsizei bufSize,
3221 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003222{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003223 if (length)
3224 {
3225 *length = 0;
3226 }
3227
Jamie Madill78f41802014-08-25 15:47:55 -04003228 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003229 {
Jamie Madill78f41802014-08-25 15:47:55 -04003230 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003231 }
3232
Geoff Langf41d0ee2016-10-07 13:04:23 -04003233 if (bufSize < 0)
3234 {
Jamie Madille0472f32018-11-27 16:32:45 -05003235 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003236 return false;
3237 }
3238
Jamie Madill44a6fbf2018-10-02 13:38:56 -04003239 Program *programObject = context->getProgramResolveLink(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003240 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003241
Jamie Madill78f41802014-08-25 15:47:55 -04003242 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003243 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003244 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003245 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003246 {
Jamie Madille0472f32018-11-27 16:32:45 -05003247 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003248 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003249 }
3250
Geoff Langf41d0ee2016-10-07 13:04:23 -04003251 if (length)
3252 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003253 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003254 }
3255
Jamie Madill0063c512014-08-25 15:47:53 -04003256 return true;
3257}
3258
He Yunchaoced53ae2016-11-29 15:00:51 +08003259bool ValidateGetnUniformfvEXT(Context *context,
3260 GLuint program,
3261 GLint location,
3262 GLsizei bufSize,
3263 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003264{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003265 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003266}
3267
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003268bool ValidateGetnUniformfvRobustANGLE(Context *context,
3269 GLuint program,
3270 GLint location,
3271 GLsizei bufSize,
3272 GLsizei *length,
3273 GLfloat *params)
3274{
3275 UNIMPLEMENTED();
3276 return false;
3277}
3278
He Yunchaoced53ae2016-11-29 15:00:51 +08003279bool ValidateGetnUniformivEXT(Context *context,
3280 GLuint program,
3281 GLint location,
3282 GLsizei bufSize,
3283 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003284{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003285 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3286}
3287
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003288bool ValidateGetnUniformivRobustANGLE(Context *context,
3289 GLuint program,
3290 GLint location,
3291 GLsizei bufSize,
3292 GLsizei *length,
3293 GLint *params)
3294{
3295 UNIMPLEMENTED();
3296 return false;
3297}
3298
3299bool ValidateGetnUniformuivRobustANGLE(Context *context,
3300 GLuint program,
3301 GLint location,
3302 GLsizei bufSize,
3303 GLsizei *length,
3304 GLuint *params)
3305{
3306 UNIMPLEMENTED();
3307 return false;
3308}
3309
Geoff Langf41d0ee2016-10-07 13:04:23 -04003310bool ValidateGetUniformfvRobustANGLE(Context *context,
3311 GLuint program,
3312 GLint location,
3313 GLsizei bufSize,
3314 GLsizei *length,
3315 GLfloat *params)
3316{
3317 if (!ValidateRobustEntryPoint(context, bufSize))
3318 {
3319 return false;
3320 }
3321
Brandon Jonesd1049182018-03-28 10:02:20 -07003322 GLsizei writeLength = 0;
3323
Geoff Langf41d0ee2016-10-07 13:04:23 -04003324 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003325 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3326 {
3327 return false;
3328 }
3329
3330 SetRobustLengthParam(length, writeLength);
3331
3332 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003333}
3334
3335bool ValidateGetUniformivRobustANGLE(Context *context,
3336 GLuint program,
3337 GLint location,
3338 GLsizei bufSize,
3339 GLsizei *length,
3340 GLint *params)
3341{
3342 if (!ValidateRobustEntryPoint(context, bufSize))
3343 {
3344 return false;
3345 }
3346
Brandon Jonesd1049182018-03-28 10:02:20 -07003347 GLsizei writeLength = 0;
3348
Geoff Langf41d0ee2016-10-07 13:04:23 -04003349 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003350 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3351 {
3352 return false;
3353 }
3354
3355 SetRobustLengthParam(length, writeLength);
3356
3357 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003358}
3359
3360bool ValidateGetUniformuivRobustANGLE(Context *context,
3361 GLuint program,
3362 GLint location,
3363 GLsizei bufSize,
3364 GLsizei *length,
3365 GLuint *params)
3366{
3367 if (!ValidateRobustEntryPoint(context, bufSize))
3368 {
3369 return false;
3370 }
3371
3372 if (context->getClientMajorVersion() < 3)
3373 {
Jamie Madille0472f32018-11-27 16:32:45 -05003374 context->validationError(GL_INVALID_OPERATION, kES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003375 return false;
3376 }
3377
Brandon Jonesd1049182018-03-28 10:02:20 -07003378 GLsizei writeLength = 0;
3379
Geoff Langf41d0ee2016-10-07 13:04:23 -04003380 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003381 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3382 {
3383 return false;
3384 }
3385
3386 SetRobustLengthParam(length, writeLength);
3387
3388 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003389}
3390
He Yunchaoced53ae2016-11-29 15:00:51 +08003391bool ValidateDiscardFramebufferBase(Context *context,
3392 GLenum target,
3393 GLsizei numAttachments,
3394 const GLenum *attachments,
3395 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003396{
3397 if (numAttachments < 0)
3398 {
Jamie Madille0472f32018-11-27 16:32:45 -05003399 context->validationError(GL_INVALID_VALUE, kNegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003400 return false;
3401 }
3402
3403 for (GLsizei i = 0; i < numAttachments; ++i)
3404 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003405 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003406 {
3407 if (defaultFramebuffer)
3408 {
Jamie Madille0472f32018-11-27 16:32:45 -05003409 context->validationError(GL_INVALID_ENUM, kDefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003410 return false;
3411 }
3412
3413 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3414 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003415 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003416 return false;
3417 }
3418 }
3419 else
3420 {
3421 switch (attachments[i])
3422 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003423 case GL_DEPTH_ATTACHMENT:
3424 case GL_STENCIL_ATTACHMENT:
3425 case GL_DEPTH_STENCIL_ATTACHMENT:
3426 if (defaultFramebuffer)
3427 {
Jamie Madill610640f2018-11-21 17:28:41 -05003428 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05003429 kDefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003430 return false;
3431 }
3432 break;
3433 case GL_COLOR:
3434 case GL_DEPTH:
3435 case GL_STENCIL:
3436 if (!defaultFramebuffer)
3437 {
Jamie Madill610640f2018-11-21 17:28:41 -05003438 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05003439 kDefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003440 return false;
3441 }
3442 break;
3443 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003444 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003445 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003446 }
3447 }
3448 }
3449
3450 return true;
3451}
3452
Austin Kinross6ee1e782015-05-29 17:05:37 -07003453bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3454{
Jamie Madill007530e2017-12-28 14:27:04 -05003455 if (!context->getExtensions().debugMarker)
3456 {
3457 // The debug marker calls should not set error state
3458 // However, it seems reasonable to set an error state if the extension is not enabled
Jamie Madille0472f32018-11-27 16:32:45 -05003459 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill007530e2017-12-28 14:27:04 -05003460 return false;
3461 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003462
Jamie Madill007530e2017-12-28 14:27:04 -05003463 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003464 if (length < 0)
3465 {
3466 return false;
3467 }
3468
3469 if (marker == nullptr)
3470 {
3471 return false;
3472 }
3473
3474 return true;
3475}
3476
3477bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3478{
Jamie Madill007530e2017-12-28 14:27:04 -05003479 if (!context->getExtensions().debugMarker)
3480 {
3481 // The debug marker calls should not set error state
3482 // However, it seems reasonable to set an error state if the extension is not enabled
Jamie Madille0472f32018-11-27 16:32:45 -05003483 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill007530e2017-12-28 14:27:04 -05003484 return false;
3485 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003486
Jamie Madill007530e2017-12-28 14:27:04 -05003487 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003488 if (length < 0)
3489 {
3490 return false;
3491 }
3492
3493 if (length > 0 && marker == nullptr)
3494 {
3495 return false;
3496 }
3497
3498 return true;
3499}
3500
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003501bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003502{
Geoff Langa8406172015-07-21 16:53:39 -04003503 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3504 {
Jamie Madille0472f32018-11-27 16:32:45 -05003505 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langa8406172015-07-21 16:53:39 -04003506 return false;
3507 }
3508
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003509 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003510 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003511 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003512 if (!context->getExtensions().eglImage)
3513 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003514 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb66a9092016-05-16 15:59:14 -04003515 }
3516 break;
3517
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003518 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003519 if (!context->getExtensions().eglImageExternal)
3520 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003521 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb66a9092016-05-16 15:59:14 -04003522 }
Geoff Langa8406172015-07-21 16:53:39 -04003523 break;
3524
3525 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003526 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003527 return false;
3528 }
3529
Rafael Cintron05a449a2018-06-20 18:08:04 -07003530 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003531
Jamie Madill61e16b42017-06-19 11:13:23 -04003532 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003533 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003534 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003535 context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
Geoff Langa8406172015-07-21 16:53:39 -04003536 return false;
3537 }
3538
Jamie Madill007530e2017-12-28 14:27:04 -05003539 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003540 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003541 context->validationError(GL_INVALID_OPERATION, kEGLImageCannotCreate2DMultisampled);
Geoff Langa8406172015-07-21 16:53:39 -04003542 return false;
3543 }
3544
Yuly Novikov2eb54072018-08-22 16:41:26 -04003545 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003546 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003547 context->validationError(GL_INVALID_OPERATION, kEGLImageTextureFormatNotSupported);
Geoff Langa8406172015-07-21 16:53:39 -04003548 return false;
3549 }
3550
Geoff Langdcab33b2015-07-21 13:03:16 -04003551 return true;
3552}
3553
3554bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003555 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003556 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003557{
Geoff Langa8406172015-07-21 16:53:39 -04003558 if (!context->getExtensions().eglImage)
3559 {
Jamie Madille0472f32018-11-27 16:32:45 -05003560 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langa8406172015-07-21 16:53:39 -04003561 return false;
3562 }
3563
3564 switch (target)
3565 {
3566 case GL_RENDERBUFFER:
3567 break;
3568
3569 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003570 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003571 return false;
3572 }
3573
Rafael Cintron05a449a2018-06-20 18:08:04 -07003574 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003575
Jamie Madill61e16b42017-06-19 11:13:23 -04003576 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003577 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003578 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003579 context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
Geoff Langa8406172015-07-21 16:53:39 -04003580 return false;
3581 }
3582
Yuly Novikov2eb54072018-08-22 16:41:26 -04003583 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003584 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003585 context->validationError(GL_INVALID_OPERATION, kEGLImageRenderbufferFormatNotSupported);
Geoff Langa8406172015-07-21 16:53:39 -04003586 return false;
3587 }
3588
Geoff Langdcab33b2015-07-21 13:03:16 -04003589 return true;
3590}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003591
3592bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3593{
Geoff Lang36167ab2015-12-07 10:27:14 -05003594 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003595 {
3596 // The default VAO should always exist
3597 ASSERT(array != 0);
Jamie Madille0472f32018-11-27 16:32:45 -05003598 context->validationError(GL_INVALID_OPERATION, kInvalidVertexArray);
Austin Kinrossbc781f32015-10-26 09:27:38 -07003599 return false;
3600 }
3601
3602 return true;
3603}
3604
Geoff Langc5629752015-12-07 16:29:04 -05003605bool ValidateProgramBinaryBase(Context *context,
3606 GLuint program,
3607 GLenum binaryFormat,
3608 const void *binary,
3609 GLint length)
3610{
3611 Program *programObject = GetValidProgram(context, program);
3612 if (programObject == nullptr)
3613 {
3614 return false;
3615 }
3616
3617 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3618 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3619 programBinaryFormats.end())
3620 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003621 context->validationError(GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
Geoff Langc5629752015-12-07 16:29:04 -05003622 return false;
3623 }
3624
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003625 if (context->hasActiveTransformFeedback(program))
3626 {
3627 // ES 3.0.4 section 2.15 page 91
Jamie Madillc3e37312018-11-30 15:25:39 -05003628 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003629 return false;
3630 }
3631
Geoff Langc5629752015-12-07 16:29:04 -05003632 return true;
3633}
3634
3635bool ValidateGetProgramBinaryBase(Context *context,
3636 GLuint program,
3637 GLsizei bufSize,
3638 GLsizei *length,
3639 GLenum *binaryFormat,
3640 void *binary)
3641{
3642 Program *programObject = GetValidProgram(context, program);
3643 if (programObject == nullptr)
3644 {
3645 return false;
3646 }
3647
3648 if (!programObject->isLinked())
3649 {
Jamie Madille0472f32018-11-27 16:32:45 -05003650 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003651 return false;
3652 }
3653
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003654 if (context->getCaps().programBinaryFormats.empty())
3655 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003656 context->validationError(GL_INVALID_OPERATION, kNoProgramBinaryFormats);
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003657 return false;
3658 }
3659
Geoff Langc5629752015-12-07 16:29:04 -05003660 return true;
3661}
Jamie Madillc29968b2016-01-20 11:17:23 -05003662
Jamie Madill5b772312018-03-08 20:28:32 -05003663bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003664{
3665 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003666 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003667 {
Jamie Madille0472f32018-11-27 16:32:45 -05003668 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Brandon Jonesafa75152017-07-21 13:11:29 -07003669 return false;
3670 }
3671 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3672 {
Jamie Madille0472f32018-11-27 16:32:45 -05003673 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003674 return false;
3675 }
3676
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003677 ASSERT(context->getGLState().getDrawFramebuffer());
3678 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003679 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3680
3681 // This should come first before the check for the default frame buffer
3682 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3683 // rather than INVALID_OPERATION
3684 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3685 {
3686 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3687
3688 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003689 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3690 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003691 {
3692 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003693 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3694 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3695 // 3.1 is still a bit ambiguous about the error, but future specs are
3696 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madillc3e37312018-11-30 15:25:39 -05003697 context->validationError(GL_INVALID_ENUM, kInvalidDrawBuffer);
Olli Etuaho84c9f592016-03-09 14:37:25 +02003698 return false;
3699 }
3700 else if (bufs[colorAttachment] >= maxColorAttachment)
3701 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003702 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
Jamie Madillc29968b2016-01-20 11:17:23 -05003703 return false;
3704 }
3705 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3706 frameBufferId != 0)
3707 {
3708 // INVALID_OPERATION-GL is bound to buffer and ith argument
3709 // is not COLOR_ATTACHMENTi or NONE
Jamie Madillc3e37312018-11-30 15:25:39 -05003710 context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferValue);
Jamie Madillc29968b2016-01-20 11:17:23 -05003711 return false;
3712 }
3713 }
3714
3715 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3716 // and n is not 1 or bufs is bound to value other than BACK and NONE
3717 if (frameBufferId == 0)
3718 {
3719 if (n != 1)
3720 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003721 context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferCountForDefault);
Jamie Madillc29968b2016-01-20 11:17:23 -05003722 return false;
3723 }
3724
3725 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3726 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003727 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferInvalidDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003728 return false;
3729 }
3730 }
3731
3732 return true;
3733}
3734
Geoff Lang496c02d2016-10-20 11:38:11 -07003735bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003736 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003737 GLenum pname,
3738 GLsizei *length,
3739 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003740{
Geoff Lang496c02d2016-10-20 11:38:11 -07003741 if (length)
3742 {
3743 *length = 0;
3744 }
3745
Corentin Walleze4477002017-12-01 14:39:58 -05003746 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003747 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003748 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003749 return false;
3750 }
3751
Geoff Lang496c02d2016-10-20 11:38:11 -07003752 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003753 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003754 case GL_BUFFER_MAP_POINTER:
3755 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003756
Geoff Lang496c02d2016-10-20 11:38:11 -07003757 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003758 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003759 return false;
3760 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003761
3762 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3763 // target bound to zero generate an INVALID_OPERATION error."
3764 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003765 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003766 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003767 context->validationError(GL_INVALID_OPERATION, kBufferPointerNotAvailable);
Olli Etuaho4f667482016-03-30 15:56:35 +03003768 return false;
3769 }
3770
Geoff Lang496c02d2016-10-20 11:38:11 -07003771 if (length)
3772 {
3773 *length = 1;
3774 }
3775
Olli Etuaho4f667482016-03-30 15:56:35 +03003776 return true;
3777}
3778
Corentin Wallez336129f2017-10-17 15:55:40 -04003779bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003780{
Corentin Walleze4477002017-12-01 14:39:58 -05003781 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003782 {
Jamie Madille0472f32018-11-27 16:32:45 -05003783 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003784 return false;
3785 }
3786
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003787 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003788
3789 if (buffer == nullptr || !buffer->isMapped())
3790 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003791 context->validationError(GL_INVALID_OPERATION, kBufferNotMapped);
Olli Etuaho4f667482016-03-30 15:56:35 +03003792 return false;
3793 }
3794
3795 return true;
3796}
3797
3798bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003799 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003800 GLintptr offset,
3801 GLsizeiptr length,
3802 GLbitfield access)
3803{
Corentin Walleze4477002017-12-01 14:39:58 -05003804 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003805 {
Jamie Madille0472f32018-11-27 16:32:45 -05003806 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003807 return false;
3808 }
3809
Brandon Jones6cad5662017-06-14 13:25:13 -07003810 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003811 {
Jamie Madille0472f32018-11-27 16:32:45 -05003812 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07003813 return false;
3814 }
3815
3816 if (length < 0)
3817 {
Jamie Madille0472f32018-11-27 16:32:45 -05003818 context->validationError(GL_INVALID_VALUE, kNegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003819 return false;
3820 }
3821
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003822 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003823
3824 if (!buffer)
3825 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003826 context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
Olli Etuaho4f667482016-03-30 15:56:35 +03003827 return false;
3828 }
3829
3830 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003831 CheckedNumeric<size_t> checkedOffset(offset);
3832 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003833
Jamie Madille2e406c2016-06-02 13:04:10 -04003834 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003835 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003836 context->validationError(GL_INVALID_VALUE, kMapOutOfRange);
Olli Etuaho4f667482016-03-30 15:56:35 +03003837 return false;
3838 }
3839
3840 // Check for invalid bits in the mask
3841 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3842 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3843 GL_MAP_UNSYNCHRONIZED_BIT;
3844
3845 if (access & ~(allAccessBits))
3846 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003847 context->validationError(GL_INVALID_VALUE, kInvalidAccessBits);
Olli Etuaho4f667482016-03-30 15:56:35 +03003848 return false;
3849 }
3850
3851 if (length == 0)
3852 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003853 context->validationError(GL_INVALID_OPERATION, kLengthZero);
Olli Etuaho4f667482016-03-30 15:56:35 +03003854 return false;
3855 }
3856
3857 if (buffer->isMapped())
3858 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003859 context->validationError(GL_INVALID_OPERATION, kBufferAlreadyMapped);
Olli Etuaho4f667482016-03-30 15:56:35 +03003860 return false;
3861 }
3862
3863 // Check for invalid bit combinations
3864 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3865 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003866 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
Olli Etuaho4f667482016-03-30 15:56:35 +03003867 return false;
3868 }
3869
3870 GLbitfield writeOnlyBits =
3871 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3872
3873 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3874 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003875 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsRead);
Olli Etuaho4f667482016-03-30 15:56:35 +03003876 return false;
3877 }
3878
3879 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3880 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003881 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 return false;
3883 }
Geoff Lang79f71042017-08-14 16:43:43 -04003884
3885 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003886}
3887
3888bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003889 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003890 GLintptr offset,
3891 GLsizeiptr length)
3892{
Brandon Jones6cad5662017-06-14 13:25:13 -07003893 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003894 {
Jamie Madille0472f32018-11-27 16:32:45 -05003895 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07003896 return false;
3897 }
3898
3899 if (length < 0)
3900 {
Jamie Madille0472f32018-11-27 16:32:45 -05003901 context->validationError(GL_INVALID_VALUE, kNegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003902 return false;
3903 }
3904
Corentin Walleze4477002017-12-01 14:39:58 -05003905 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003906 {
Jamie Madille0472f32018-11-27 16:32:45 -05003907 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 return false;
3909 }
3910
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003911 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003912
3913 if (buffer == nullptr)
3914 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003915 context->validationError(GL_INVALID_OPERATION, kInvalidFlushZero);
Olli Etuaho4f667482016-03-30 15:56:35 +03003916 return false;
3917 }
3918
3919 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3920 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003921 context->validationError(GL_INVALID_OPERATION, kInvalidFlushTarget);
Olli Etuaho4f667482016-03-30 15:56:35 +03003922 return false;
3923 }
3924
3925 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003926 CheckedNumeric<size_t> checkedOffset(offset);
3927 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003928
Jamie Madille2e406c2016-06-02 13:04:10 -04003929 if (!checkedSize.IsValid() ||
3930 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003931 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003932 context->validationError(GL_INVALID_VALUE, kInvalidFlushOutOfRange);
Olli Etuaho4f667482016-03-30 15:56:35 +03003933 return false;
3934 }
3935
3936 return true;
3937}
3938
Olli Etuaho41997e72016-03-10 13:38:39 +02003939bool ValidateGenOrDelete(Context *context, GLint n)
3940{
3941 if (n < 0)
3942 {
Jamie Madille0472f32018-11-27 16:32:45 -05003943 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003944 return false;
3945 }
3946 return true;
3947}
3948
Jamie Madill5b772312018-03-08 20:28:32 -05003949bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003950{
3951 if (!context->getExtensions().robustClientMemory)
3952 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003953 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langff5b2d52016-09-07 11:32:23 -04003954 return false;
3955 }
3956
3957 if (bufSize < 0)
3958 {
Jamie Madille0472f32018-11-27 16:32:45 -05003959 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003960 return false;
3961 }
3962
3963 return true;
3964}
3965
Jamie Madill5b772312018-03-08 20:28:32 -05003966bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003967{
3968 if (bufSize < numParams)
3969 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003970 context->validationError(GL_INVALID_OPERATION, kInsufficientParams);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003971 return false;
3972 }
3973
3974 return true;
3975}
3976
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003977bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003978 GLenum target,
3979 GLenum attachment,
3980 GLenum pname,
3981 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003982{
Geoff Lange8afa902017-09-27 15:00:43 -04003983 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003984 {
Jamie Madille0472f32018-11-27 16:32:45 -05003985 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003986 return false;
3987 }
3988
3989 int clientVersion = context->getClientMajorVersion();
3990
3991 switch (pname)
3992 {
3993 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3994 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3995 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3996 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3997 break;
3998
Martin Radeve5285d22017-07-14 16:23:53 +03003999 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4000 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4001 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4002 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4003 if (clientVersion < 3 || !context->getExtensions().multiview)
4004 {
Jamie Madille0472f32018-11-27 16:32:45 -05004005 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Martin Radeve5285d22017-07-14 16:23:53 +03004006 return false;
4007 }
4008 break;
4009
Geoff Langff5b2d52016-09-07 11:32:23 -04004010 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4011 if (clientVersion < 3 && !context->getExtensions().sRGB)
4012 {
Jamie Madille0472f32018-11-27 16:32:45 -05004013 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004014 return false;
4015 }
4016 break;
4017
4018 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4019 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4020 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4021 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4022 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4023 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4024 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4025 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4026 if (clientVersion < 3)
4027 {
Jamie Madille0472f32018-11-27 16:32:45 -05004028 context->validationError(GL_INVALID_ENUM, kES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004029 return false;
4030 }
4031 break;
4032
Jiawei Shaoa8802472018-05-28 11:17:47 +08004033 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4034 if (!context->getExtensions().geometryShader)
4035 {
Jamie Madille0472f32018-11-27 16:32:45 -05004036 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shaoa8802472018-05-28 11:17:47 +08004037 return false;
4038 }
4039 break;
4040
Geoff Langff5b2d52016-09-07 11:32:23 -04004041 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004042 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Geoff Langff5b2d52016-09-07 11:32:23 -04004043 return false;
4044 }
4045
4046 // Determine if the attachment is a valid enum
4047 switch (attachment)
4048 {
4049 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004050 case GL_DEPTH:
4051 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004052 if (clientVersion < 3)
4053 {
Jamie Madille0472f32018-11-27 16:32:45 -05004054 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004055 return false;
4056 }
4057 break;
4058
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004059 case GL_DEPTH_STENCIL_ATTACHMENT:
4060 if (clientVersion < 3 && !context->isWebGL1())
4061 {
Jamie Madille0472f32018-11-27 16:32:45 -05004062 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004063 return false;
4064 }
4065 break;
4066
Geoff Langfa125c92017-10-24 13:01:46 -04004067 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004068 case GL_DEPTH_ATTACHMENT:
4069 case GL_STENCIL_ATTACHMENT:
4070 break;
4071
4072 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004073 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4074 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004075 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4076 {
Jamie Madille0472f32018-11-27 16:32:45 -05004077 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004078 return false;
4079 }
4080 break;
4081 }
4082
4083 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4084 ASSERT(framebuffer);
4085
4086 if (framebuffer->id() == 0)
4087 {
4088 if (clientVersion < 3)
4089 {
Jamie Madille0472f32018-11-27 16:32:45 -05004090 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004091 return false;
4092 }
4093
4094 switch (attachment)
4095 {
4096 case GL_BACK:
4097 case GL_DEPTH:
4098 case GL_STENCIL:
4099 break;
4100
4101 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004102 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004103 return false;
4104 }
4105 }
4106 else
4107 {
4108 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4109 {
4110 // Valid attachment query
4111 }
4112 else
4113 {
4114 switch (attachment)
4115 {
4116 case GL_DEPTH_ATTACHMENT:
4117 case GL_STENCIL_ATTACHMENT:
4118 break;
4119
4120 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004121 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004122 {
Jamie Madille0472f32018-11-27 16:32:45 -05004123 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004124 return false;
4125 }
4126 break;
4127
4128 default:
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 }
4133 }
4134
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004135 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004136 if (attachmentObject)
4137 {
4138 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4139 attachmentObject->type() == GL_TEXTURE ||
4140 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4141
4142 switch (pname)
4143 {
4144 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4145 if (attachmentObject->type() != GL_RENDERBUFFER &&
4146 attachmentObject->type() != GL_TEXTURE)
4147 {
Jamie Madille0472f32018-11-27 16:32:45 -05004148 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004149 return false;
4150 }
4151 break;
4152
4153 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4154 if (attachmentObject->type() != GL_TEXTURE)
4155 {
Jamie Madille0472f32018-11-27 16:32:45 -05004156 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004157 return false;
4158 }
4159 break;
4160
4161 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4162 if (attachmentObject->type() != GL_TEXTURE)
4163 {
Jamie Madille0472f32018-11-27 16:32:45 -05004164 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004165 return false;
4166 }
4167 break;
4168
4169 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4170 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4171 {
Jamie Madille0472f32018-11-27 16:32:45 -05004172 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004173 return false;
4174 }
4175 break;
4176
4177 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4178 if (attachmentObject->type() != GL_TEXTURE)
4179 {
Jamie Madille0472f32018-11-27 16:32:45 -05004180 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004181 return false;
4182 }
4183 break;
4184
4185 default:
4186 break;
4187 }
4188 }
4189 else
4190 {
4191 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4192 // is NONE, then querying any other pname will generate INVALID_ENUM.
4193
4194 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4195 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4196 // INVALID_OPERATION for all other pnames
4197
4198 switch (pname)
4199 {
4200 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4201 break;
4202
4203 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4204 if (clientVersion < 3)
4205 {
Jamie Madill610640f2018-11-21 17:28:41 -05004206 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05004207 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004208 return false;
4209 }
4210 break;
4211
4212 default:
4213 if (clientVersion < 3)
4214 {
Jamie Madill610640f2018-11-21 17:28:41 -05004215 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05004216 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004217 return false;
4218 }
4219 else
4220 {
Jamie Madill610640f2018-11-21 17:28:41 -05004221 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05004222 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004223 return false;
4224 }
4225 }
4226 }
4227
Martin Radeve5285d22017-07-14 16:23:53 +03004228 if (numParams)
4229 {
4230 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4231 {
4232 // Only when the viewport offsets are queried we can have a varying number of output
4233 // parameters.
4234 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4235 *numParams = numViews * 2;
4236 }
4237 else
4238 {
4239 // For all other queries we can have only one output parameter.
4240 *numParams = 1;
4241 }
4242 }
4243
Geoff Langff5b2d52016-09-07 11:32:23 -04004244 return true;
4245}
4246
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004247bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004248 GLenum target,
4249 GLenum attachment,
4250 GLenum pname,
4251 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004252 GLsizei *length,
4253 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004254{
4255 if (!ValidateRobustEntryPoint(context, bufSize))
4256 {
4257 return false;
4258 }
4259
Brandon Jonesd1049182018-03-28 10:02:20 -07004260 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004261 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004262 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004263 {
4264 return false;
4265 }
4266
Brandon Jonesd1049182018-03-28 10:02:20 -07004267 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004268 {
4269 return false;
4270 }
4271
Brandon Jonesd1049182018-03-28 10:02:20 -07004272 SetRobustLengthParam(length, numParams);
4273
Geoff Langff5b2d52016-09-07 11:32:23 -04004274 return true;
4275}
4276
Jamie Madill5b772312018-03-08 20:28:32 -05004277bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004278 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004279 GLenum pname,
4280 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004281 GLsizei *length,
4282 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004283{
4284 if (!ValidateRobustEntryPoint(context, bufSize))
4285 {
4286 return false;
4287 }
4288
Brandon Jonesd1049182018-03-28 10:02:20 -07004289 GLsizei numParams = 0;
4290
4291 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004292 {
4293 return false;
4294 }
4295
Brandon Jonesd1049182018-03-28 10:02:20 -07004296 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004297 {
4298 return false;
4299 }
4300
Brandon Jonesd1049182018-03-28 10:02:20 -07004301 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004302 return true;
4303}
4304
Jamie Madill5b772312018-03-08 20:28:32 -05004305bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004306 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004307 GLenum pname,
4308 GLsizei bufSize,
4309 GLsizei *length,
4310 GLint64 *params)
4311{
Brandon Jonesd1049182018-03-28 10:02:20 -07004312 GLsizei numParams = 0;
4313
Geoff Langebebe1c2016-10-14 12:01:31 -04004314 if (!ValidateRobustEntryPoint(context, bufSize))
4315 {
4316 return false;
4317 }
4318
Brandon Jonesd1049182018-03-28 10:02:20 -07004319 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004320 {
4321 return false;
4322 }
4323
Brandon Jonesd1049182018-03-28 10:02:20 -07004324 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004325 {
4326 return false;
4327 }
4328
Brandon Jonesd1049182018-03-28 10:02:20 -07004329 SetRobustLengthParam(length, numParams);
4330
Geoff Langff5b2d52016-09-07 11:32:23 -04004331 return true;
4332}
4333
Jamie Madill5b772312018-03-08 20:28:32 -05004334bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004335{
4336 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004337 if (numParams)
4338 {
4339 *numParams = 1;
4340 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004341
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004342 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
4343 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
4344 ? GetValidProgramNoResolve(context, program)
4345 : GetValidProgram(context, program);
Geoff Langff5b2d52016-09-07 11:32:23 -04004346 if (!programObject)
4347 {
4348 return false;
4349 }
4350
4351 switch (pname)
4352 {
4353 case GL_DELETE_STATUS:
4354 case GL_LINK_STATUS:
4355 case GL_VALIDATE_STATUS:
4356 case GL_INFO_LOG_LENGTH:
4357 case GL_ATTACHED_SHADERS:
4358 case GL_ACTIVE_ATTRIBUTES:
4359 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4360 case GL_ACTIVE_UNIFORMS:
4361 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4362 break;
4363
4364 case GL_PROGRAM_BINARY_LENGTH:
4365 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4366 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004367 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004368 return false;
4369 }
4370 break;
4371
4372 case GL_ACTIVE_UNIFORM_BLOCKS:
4373 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4374 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4375 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4376 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4377 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4378 if (context->getClientMajorVersion() < 3)
4379 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004380 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Geoff Langff5b2d52016-09-07 11:32:23 -04004381 return false;
4382 }
4383 break;
4384
Yunchao He61afff12017-03-14 15:34:03 +08004385 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004386 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004387 if (context->getClientVersion() < Version(3, 1))
4388 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004389 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Yunchao He61afff12017-03-14 15:34:03 +08004390 return false;
4391 }
4392 break;
4393
Jiawei Shao6ae51612018-02-23 14:03:25 +08004394 case GL_COMPUTE_WORK_GROUP_SIZE:
4395 if (context->getClientVersion() < Version(3, 1))
4396 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004397 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004398 return false;
4399 }
4400
4401 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4402 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4403 // program which has not been linked successfully, or which does not contain objects to
4404 // form a compute shader.
4405 if (!programObject->isLinked())
4406 {
Jamie Madille0472f32018-11-27 16:32:45 -05004407 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004408 return false;
4409 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004410 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004411 {
Jamie Madille0472f32018-11-27 16:32:45 -05004412 context->validationError(GL_INVALID_OPERATION, kNoActiveComputeShaderStage);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004413 return false;
4414 }
4415 break;
4416
Jiawei Shao447bfac2018-03-14 14:23:40 +08004417 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4418 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4419 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4420 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4421 if (!context->getExtensions().geometryShader)
4422 {
Jamie Madille0472f32018-11-27 16:32:45 -05004423 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004424 return false;
4425 }
4426
4427 // [EXT_geometry_shader] Chapter 7.12
4428 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4429 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4430 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4431 // successfully, or which does not contain objects to form a geometry shader.
4432 if (!programObject->isLinked())
4433 {
Jamie Madille0472f32018-11-27 16:32:45 -05004434 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004435 return false;
4436 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004437 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004438 {
Jamie Madille0472f32018-11-27 16:32:45 -05004439 context->validationError(GL_INVALID_OPERATION, kNoActiveGeometryShaderStage);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004440 return false;
4441 }
4442 break;
4443
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004444 case GL_COMPLETION_STATUS_KHR:
4445 if (!context->getExtensions().parallelShaderCompile)
4446 {
Jamie Madille0472f32018-11-27 16:32:45 -05004447 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004448 return false;
4449 }
4450 break;
4451
Geoff Langff5b2d52016-09-07 11:32:23 -04004452 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004453 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004454 return false;
4455 }
4456
4457 return true;
4458}
4459
4460bool ValidateGetProgramivRobustANGLE(Context *context,
4461 GLuint program,
4462 GLenum pname,
4463 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004464 GLsizei *length,
4465 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004466{
4467 if (!ValidateRobustEntryPoint(context, bufSize))
4468 {
4469 return false;
4470 }
4471
Brandon Jonesd1049182018-03-28 10:02:20 -07004472 GLsizei numParams = 0;
4473
4474 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004475 {
4476 return false;
4477 }
4478
Brandon Jonesd1049182018-03-28 10:02:20 -07004479 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004480 {
4481 return false;
4482 }
4483
Brandon Jonesd1049182018-03-28 10:02:20 -07004484 SetRobustLengthParam(length, numParams);
4485
Geoff Langff5b2d52016-09-07 11:32:23 -04004486 return true;
4487}
4488
Geoff Lang740d9022016-10-07 11:20:52 -04004489bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4490 GLenum target,
4491 GLenum pname,
4492 GLsizei bufSize,
4493 GLsizei *length,
4494 GLint *params)
4495{
4496 if (!ValidateRobustEntryPoint(context, bufSize))
4497 {
4498 return false;
4499 }
4500
Brandon Jonesd1049182018-03-28 10:02:20 -07004501 GLsizei numParams = 0;
4502
4503 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004504 {
4505 return false;
4506 }
4507
Brandon Jonesd1049182018-03-28 10:02:20 -07004508 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004509 {
4510 return false;
4511 }
4512
Brandon Jonesd1049182018-03-28 10:02:20 -07004513 SetRobustLengthParam(length, numParams);
4514
Geoff Lang740d9022016-10-07 11:20:52 -04004515 return true;
4516}
4517
Geoff Langd7d0ed32016-10-07 11:33:51 -04004518bool ValidateGetShaderivRobustANGLE(Context *context,
4519 GLuint shader,
4520 GLenum pname,
4521 GLsizei bufSize,
4522 GLsizei *length,
4523 GLint *params)
4524{
4525 if (!ValidateRobustEntryPoint(context, bufSize))
4526 {
4527 return false;
4528 }
4529
Brandon Jonesd1049182018-03-28 10:02:20 -07004530 GLsizei numParams = 0;
4531
4532 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004533 {
4534 return false;
4535 }
4536
Brandon Jonesd1049182018-03-28 10:02:20 -07004537 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004538 {
4539 return false;
4540 }
4541
Brandon Jonesd1049182018-03-28 10:02:20 -07004542 SetRobustLengthParam(length, numParams);
4543
Geoff Langd7d0ed32016-10-07 11:33:51 -04004544 return true;
4545}
4546
Geoff Langc1984ed2016-10-07 12:41:00 -04004547bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004548 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004549 GLenum pname,
4550 GLsizei bufSize,
4551 GLsizei *length,
4552 GLfloat *params)
4553{
4554 if (!ValidateRobustEntryPoint(context, bufSize))
4555 {
4556 return false;
4557 }
4558
Brandon Jonesd1049182018-03-28 10:02:20 -07004559 GLsizei numParams = 0;
4560
4561 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004562 {
4563 return false;
4564 }
4565
Brandon Jonesd1049182018-03-28 10:02:20 -07004566 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004567 {
4568 return false;
4569 }
4570
Brandon Jonesd1049182018-03-28 10:02:20 -07004571 SetRobustLengthParam(length, numParams);
4572
Geoff Langc1984ed2016-10-07 12:41:00 -04004573 return true;
4574}
4575
Geoff Langc1984ed2016-10-07 12:41:00 -04004576bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004577 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004578 GLenum pname,
4579 GLsizei bufSize,
4580 GLsizei *length,
4581 GLint *params)
4582{
Brandon Jonesd1049182018-03-28 10:02:20 -07004583
Geoff Langc1984ed2016-10-07 12:41:00 -04004584 if (!ValidateRobustEntryPoint(context, bufSize))
4585 {
4586 return false;
4587 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004588 GLsizei numParams = 0;
4589 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004590 {
4591 return false;
4592 }
4593
Brandon Jonesd1049182018-03-28 10:02:20 -07004594 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004595 {
4596 return false;
4597 }
4598
Brandon Jonesd1049182018-03-28 10:02:20 -07004599 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004600 return true;
4601}
4602
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004603bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4604 TextureType target,
4605 GLenum pname,
4606 GLsizei bufSize,
4607 GLsizei *length,
4608 GLint *params)
4609{
4610 UNIMPLEMENTED();
4611 return false;
4612}
4613
4614bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4615 TextureType target,
4616 GLenum pname,
4617 GLsizei bufSize,
4618 GLsizei *length,
4619 GLuint *params)
4620{
4621 UNIMPLEMENTED();
4622 return false;
4623}
4624
Geoff Langc1984ed2016-10-07 12:41:00 -04004625bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004626 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004627 GLenum pname,
4628 GLsizei bufSize,
4629 const GLfloat *params)
4630{
4631 if (!ValidateRobustEntryPoint(context, bufSize))
4632 {
4633 return false;
4634 }
4635
Till Rathmannb8543632018-10-02 19:46:14 +02004636 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004637}
4638
Geoff Langc1984ed2016-10-07 12:41:00 -04004639bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004640 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004641 GLenum pname,
4642 GLsizei bufSize,
4643 const GLint *params)
4644{
4645 if (!ValidateRobustEntryPoint(context, bufSize))
4646 {
4647 return false;
4648 }
4649
Till Rathmannb8543632018-10-02 19:46:14 +02004650 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004651}
4652
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004653bool ValidateTexParameterIivRobustANGLE(Context *context,
4654 TextureType target,
4655 GLenum pname,
4656 GLsizei bufSize,
4657 const GLint *params)
4658{
4659 UNIMPLEMENTED();
4660 return false;
4661}
4662
4663bool ValidateTexParameterIuivRobustANGLE(Context *context,
4664 TextureType target,
4665 GLenum pname,
4666 GLsizei bufSize,
4667 const GLuint *params)
4668{
4669 UNIMPLEMENTED();
4670 return false;
4671}
4672
Geoff Langc1984ed2016-10-07 12:41:00 -04004673bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4674 GLuint sampler,
4675 GLenum pname,
Jamie Madill778bf092018-11-14 09:54:36 -05004676 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004677 GLsizei *length,
4678 GLfloat *params)
4679{
4680 if (!ValidateRobustEntryPoint(context, bufSize))
4681 {
4682 return false;
4683 }
4684
Brandon Jonesd1049182018-03-28 10:02:20 -07004685 GLsizei numParams = 0;
4686
4687 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004688 {
4689 return false;
4690 }
4691
Brandon Jonesd1049182018-03-28 10:02:20 -07004692 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004693 {
4694 return false;
4695 }
4696
Brandon Jonesd1049182018-03-28 10:02:20 -07004697 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004698 return true;
4699}
4700
Geoff Langc1984ed2016-10-07 12:41:00 -04004701bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4702 GLuint sampler,
4703 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004704 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004705 GLsizei *length,
4706 GLint *params)
4707{
4708 if (!ValidateRobustEntryPoint(context, bufSize))
4709 {
4710 return false;
4711 }
4712
Brandon Jonesd1049182018-03-28 10:02:20 -07004713 GLsizei numParams = 0;
4714
4715 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004716 {
4717 return false;
4718 }
4719
Brandon Jonesd1049182018-03-28 10:02:20 -07004720 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004721 {
4722 return false;
4723 }
4724
Brandon Jonesd1049182018-03-28 10:02:20 -07004725 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004726 return true;
4727}
4728
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004729bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4730 GLuint sampler,
4731 GLenum pname,
4732 GLsizei bufSize,
4733 GLsizei *length,
4734 GLint *params)
4735{
4736 UNIMPLEMENTED();
4737 return false;
4738}
4739
4740bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4741 GLuint sampler,
4742 GLenum pname,
4743 GLsizei bufSize,
4744 GLsizei *length,
4745 GLuint *params)
4746{
4747 UNIMPLEMENTED();
4748 return false;
4749}
4750
Geoff Langc1984ed2016-10-07 12:41:00 -04004751bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4752 GLuint sampler,
4753 GLenum pname,
4754 GLsizei bufSize,
4755 const GLfloat *params)
4756{
4757 if (!ValidateRobustEntryPoint(context, bufSize))
4758 {
4759 return false;
4760 }
4761
Till Rathmannb8543632018-10-02 19:46:14 +02004762 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004763}
4764
Geoff Langc1984ed2016-10-07 12:41:00 -04004765bool ValidateSamplerParameterivRobustANGLE(Context *context,
4766 GLuint sampler,
4767 GLenum pname,
4768 GLsizei bufSize,
4769 const GLint *params)
4770{
4771 if (!ValidateRobustEntryPoint(context, bufSize))
4772 {
4773 return false;
4774 }
4775
Till Rathmannb8543632018-10-02 19:46:14 +02004776 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004777}
4778
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004779bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4780 GLuint sampler,
4781 GLenum pname,
4782 GLsizei bufSize,
4783 const GLint *param)
4784{
4785 UNIMPLEMENTED();
4786 return false;
4787}
4788
4789bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4790 GLuint sampler,
4791 GLenum pname,
4792 GLsizei bufSize,
4793 const GLuint *param)
4794{
4795 UNIMPLEMENTED();
4796 return false;
4797}
4798
Geoff Lang0b031062016-10-13 14:30:04 -04004799bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4800 GLuint index,
4801 GLenum pname,
4802 GLsizei bufSize,
4803 GLsizei *length,
4804 GLfloat *params)
4805{
4806 if (!ValidateRobustEntryPoint(context, bufSize))
4807 {
4808 return false;
4809 }
4810
Brandon Jonesd1049182018-03-28 10:02:20 -07004811 GLsizei writeLength = 0;
4812
4813 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004814 {
4815 return false;
4816 }
4817
Brandon Jonesd1049182018-03-28 10:02:20 -07004818 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004819 {
4820 return false;
4821 }
4822
Brandon Jonesd1049182018-03-28 10:02:20 -07004823 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004824 return true;
4825}
4826
Geoff Lang0b031062016-10-13 14:30:04 -04004827bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4828 GLuint index,
4829 GLenum pname,
4830 GLsizei bufSize,
4831 GLsizei *length,
4832 GLint *params)
4833{
4834 if (!ValidateRobustEntryPoint(context, bufSize))
4835 {
4836 return false;
4837 }
4838
Brandon Jonesd1049182018-03-28 10:02:20 -07004839 GLsizei writeLength = 0;
4840
4841 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004842 {
4843 return false;
4844 }
4845
Brandon Jonesd1049182018-03-28 10:02:20 -07004846 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004847 {
4848 return false;
4849 }
4850
Brandon Jonesd1049182018-03-28 10:02:20 -07004851 SetRobustLengthParam(length, writeLength);
4852
Geoff Lang0b031062016-10-13 14:30:04 -04004853 return true;
4854}
4855
Geoff Lang0b031062016-10-13 14:30:04 -04004856bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4857 GLuint index,
4858 GLenum pname,
4859 GLsizei bufSize,
4860 GLsizei *length,
4861 void **pointer)
4862{
4863 if (!ValidateRobustEntryPoint(context, bufSize))
4864 {
4865 return false;
4866 }
4867
Brandon Jonesd1049182018-03-28 10:02:20 -07004868 GLsizei writeLength = 0;
4869
4870 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004871 {
4872 return false;
4873 }
4874
Brandon Jonesd1049182018-03-28 10:02:20 -07004875 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004876 {
4877 return false;
4878 }
4879
Brandon Jonesd1049182018-03-28 10:02:20 -07004880 SetRobustLengthParam(length, writeLength);
4881
Geoff Lang0b031062016-10-13 14:30:04 -04004882 return true;
4883}
4884
Geoff Lang0b031062016-10-13 14:30:04 -04004885bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4886 GLuint index,
4887 GLenum pname,
4888 GLsizei bufSize,
4889 GLsizei *length,
4890 GLint *params)
4891{
4892 if (!ValidateRobustEntryPoint(context, bufSize))
4893 {
4894 return false;
4895 }
4896
Brandon Jonesd1049182018-03-28 10:02:20 -07004897 GLsizei writeLength = 0;
4898
4899 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004900 {
4901 return false;
4902 }
4903
Brandon Jonesd1049182018-03-28 10:02:20 -07004904 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004905 {
4906 return false;
4907 }
4908
Brandon Jonesd1049182018-03-28 10:02:20 -07004909 SetRobustLengthParam(length, writeLength);
4910
Geoff Lang0b031062016-10-13 14:30:04 -04004911 return true;
4912}
4913
Geoff Lang0b031062016-10-13 14:30:04 -04004914bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4915 GLuint index,
4916 GLenum pname,
4917 GLsizei bufSize,
4918 GLsizei *length,
4919 GLuint *params)
4920{
4921 if (!ValidateRobustEntryPoint(context, bufSize))
4922 {
4923 return false;
4924 }
4925
Brandon Jonesd1049182018-03-28 10:02:20 -07004926 GLsizei writeLength = 0;
4927
4928 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004929 {
4930 return false;
4931 }
4932
Brandon Jonesd1049182018-03-28 10:02:20 -07004933 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004934 {
4935 return false;
4936 }
4937
Brandon Jonesd1049182018-03-28 10:02:20 -07004938 SetRobustLengthParam(length, writeLength);
4939
Geoff Lang0b031062016-10-13 14:30:04 -04004940 return true;
4941}
4942
Geoff Lang6899b872016-10-14 11:30:13 -04004943bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4944 GLuint program,
4945 GLuint uniformBlockIndex,
4946 GLenum pname,
4947 GLsizei bufSize,
4948 GLsizei *length,
4949 GLint *params)
4950{
4951 if (!ValidateRobustEntryPoint(context, bufSize))
4952 {
4953 return false;
4954 }
4955
Brandon Jonesd1049182018-03-28 10:02:20 -07004956 GLsizei writeLength = 0;
4957
4958 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4959 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004960 {
4961 return false;
4962 }
4963
Brandon Jonesd1049182018-03-28 10:02:20 -07004964 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004965 {
4966 return false;
4967 }
4968
Brandon Jonesd1049182018-03-28 10:02:20 -07004969 SetRobustLengthParam(length, writeLength);
4970
Geoff Lang6899b872016-10-14 11:30:13 -04004971 return true;
4972}
4973
Brandon Jones416aaf92018-04-10 08:10:16 -07004974bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004975 GLenum target,
4976 GLenum internalformat,
4977 GLenum pname,
4978 GLsizei bufSize,
4979 GLsizei *length,
4980 GLint *params)
4981{
4982 if (!ValidateRobustEntryPoint(context, bufSize))
4983 {
4984 return false;
4985 }
4986
Brandon Jonesd1049182018-03-28 10:02:20 -07004987 GLsizei numParams = 0;
4988
4989 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4990 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07004991 {
4992 return false;
4993 }
4994
Brandon Jonesd1049182018-03-28 10:02:20 -07004995 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07004996 {
4997 return false;
4998 }
4999
Brandon Jonesd1049182018-03-28 10:02:20 -07005000 SetRobustLengthParam(length, numParams);
5001
Geoff Lang0a9661f2016-10-20 10:59:20 -07005002 return true;
5003}
5004
Jamie Madill5b772312018-03-08 20:28:32 -05005005bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005006 GLuint attribIndex,
5007 GLint size,
5008 GLenum type,
5009 GLboolean pureInteger)
5010{
5011 const Caps &caps = context->getCaps();
5012 if (attribIndex >= caps.maxVertexAttributes)
5013 {
Jamie Madille0472f32018-11-27 16:32:45 -05005014 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005015 return false;
5016 }
5017
5018 if (size < 1 || size > 4)
5019 {
Jamie Madille0472f32018-11-27 16:32:45 -05005020 context->validationError(GL_INVALID_VALUE, kInvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005021 return false;
Shao80957d92017-02-20 21:25:59 +08005022 }
5023
5024 switch (type)
5025 {
5026 case GL_BYTE:
5027 case GL_UNSIGNED_BYTE:
5028 case GL_SHORT:
5029 case GL_UNSIGNED_SHORT:
5030 break;
5031
5032 case GL_INT:
5033 case GL_UNSIGNED_INT:
5034 if (context->getClientMajorVersion() < 3)
5035 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005036 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005037 return false;
5038 }
5039 break;
5040
5041 case GL_FIXED:
5042 case GL_FLOAT:
5043 if (pureInteger)
5044 {
Jamie Madille0472f32018-11-27 16:32:45 -05005045 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005046 return false;
5047 }
5048 break;
5049
5050 case GL_HALF_FLOAT:
5051 if (context->getClientMajorVersion() < 3)
5052 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005053 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005054 return false;
5055 }
5056 if (pureInteger)
5057 {
Jamie Madille0472f32018-11-27 16:32:45 -05005058 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005059 return false;
5060 }
5061 break;
5062
5063 case GL_INT_2_10_10_10_REV:
5064 case GL_UNSIGNED_INT_2_10_10_10_REV:
5065 if (context->getClientMajorVersion() < 3)
5066 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005067 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005068 return false;
5069 }
5070 if (pureInteger)
5071 {
Jamie Madille0472f32018-11-27 16:32:45 -05005072 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005073 return false;
5074 }
5075 if (size != 4)
5076 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005077 context->validationError(GL_INVALID_OPERATION, kInvalidVertexAttribSize2101010);
Shao80957d92017-02-20 21:25:59 +08005078 return false;
5079 }
5080 break;
5081
5082 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005083 context->validationError(GL_INVALID_ENUM, kInvalidType);
Shao80957d92017-02-20 21:25:59 +08005084 return false;
5085 }
5086
5087 return true;
5088}
5089
Geoff Lang76e65652017-03-27 14:58:02 -04005090// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5091// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5092// specified clear value and the type of a buffer that is being cleared generates an
5093// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005094bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005095 GLint drawbuffer,
5096 const GLenum *validComponentTypes,
5097 size_t validComponentTypeCount)
5098{
5099 const FramebufferAttachment *attachment =
5100 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5101 if (attachment)
5102 {
5103 GLenum componentType = attachment->getFormat().info->componentType;
5104 const GLenum *end = validComponentTypes + validComponentTypeCount;
5105 if (std::find(validComponentTypes, end, componentType) == end)
5106 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005107 context->validationError(GL_INVALID_OPERATION, kNoDefinedClearConversion);
Geoff Lang76e65652017-03-27 14:58:02 -04005108 return false;
5109 }
5110 }
5111
5112 return true;
5113}
5114
Jamie Madill5b772312018-03-08 20:28:32 -05005115bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005116{
5117 if (!ValidateRobustEntryPoint(context, dataSize))
5118 {
5119 return false;
5120 }
5121
Jamie Madill43da7c42018-08-01 11:34:49 -04005122 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005123 if (pixelUnpackBuffer == nullptr)
5124 {
5125 if (dataSize < imageSize)
5126 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005127 context->validationError(GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
Corentin Wallezb2931602017-04-11 15:58:57 -04005128 }
5129 }
5130 return true;
5131}
5132
Jamie Madill5b772312018-03-08 20:28:32 -05005133bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005134 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005135 GLenum pname,
5136 bool pointerVersion,
5137 GLsizei *numParams)
5138{
5139 if (numParams)
5140 {
5141 *numParams = 0;
5142 }
5143
Corentin Walleze4477002017-12-01 14:39:58 -05005144 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005145 {
Jamie Madille0472f32018-11-27 16:32:45 -05005146 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005147 return false;
5148 }
5149
5150 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5151 if (!buffer)
5152 {
5153 // A null buffer means that "0" is bound to the requested buffer target
Jamie Madille0472f32018-11-27 16:32:45 -05005154 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005155 return false;
5156 }
5157
5158 const Extensions &extensions = context->getExtensions();
5159
5160 switch (pname)
5161 {
5162 case GL_BUFFER_USAGE:
5163 case GL_BUFFER_SIZE:
5164 break;
5165
5166 case GL_BUFFER_ACCESS_OES:
5167 if (!extensions.mapBuffer)
5168 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005169 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005170 return false;
5171 }
5172 break;
5173
5174 case GL_BUFFER_MAPPED:
5175 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5176 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5177 !extensions.mapBufferRange)
5178 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005179 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005180 return false;
5181 }
5182 break;
5183
5184 case GL_BUFFER_MAP_POINTER:
5185 if (!pointerVersion)
5186 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005187 context->validationError(GL_INVALID_ENUM, kInvalidMapPointerQuery);
Jamie Madillbe849e42017-05-02 15:49:00 -04005188 return false;
5189 }
5190 break;
5191
5192 case GL_BUFFER_ACCESS_FLAGS:
5193 case GL_BUFFER_MAP_OFFSET:
5194 case GL_BUFFER_MAP_LENGTH:
5195 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5196 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005197 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005198 return false;
5199 }
5200 break;
5201
Geoff Lang79b91402018-10-04 15:11:30 -04005202 case GL_MEMORY_SIZE_ANGLE:
5203 if (!context->getExtensions().memorySize)
5204 {
Jamie Madille0472f32018-11-27 16:32:45 -05005205 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Geoff Lang79b91402018-10-04 15:11:30 -04005206 return false;
5207 }
5208 break;
5209
Jamie Madillbe849e42017-05-02 15:49:00 -04005210 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005211 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005212 return false;
5213 }
5214
5215 // All buffer parameter queries return one value.
5216 if (numParams)
5217 {
5218 *numParams = 1;
5219 }
5220
5221 return true;
5222}
5223
5224bool ValidateGetRenderbufferParameterivBase(Context *context,
5225 GLenum target,
5226 GLenum pname,
5227 GLsizei *length)
5228{
5229 if (length)
5230 {
5231 *length = 0;
5232 }
5233
5234 if (target != GL_RENDERBUFFER)
5235 {
Jamie Madille0472f32018-11-27 16:32:45 -05005236 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005237 return false;
5238 }
5239
5240 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5241 if (renderbuffer == nullptr)
5242 {
Jamie Madille0472f32018-11-27 16:32:45 -05005243 context->validationError(GL_INVALID_OPERATION, kRenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005244 return false;
5245 }
5246
5247 switch (pname)
5248 {
5249 case GL_RENDERBUFFER_WIDTH:
5250 case GL_RENDERBUFFER_HEIGHT:
5251 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5252 case GL_RENDERBUFFER_RED_SIZE:
5253 case GL_RENDERBUFFER_GREEN_SIZE:
5254 case GL_RENDERBUFFER_BLUE_SIZE:
5255 case GL_RENDERBUFFER_ALPHA_SIZE:
5256 case GL_RENDERBUFFER_DEPTH_SIZE:
5257 case GL_RENDERBUFFER_STENCIL_SIZE:
5258 break;
5259
5260 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5261 if (!context->getExtensions().framebufferMultisample)
5262 {
Jamie Madille0472f32018-11-27 16:32:45 -05005263 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005264 return false;
5265 }
5266 break;
5267
Geoff Lang79b91402018-10-04 15:11:30 -04005268 case GL_MEMORY_SIZE_ANGLE:
5269 if (!context->getExtensions().memorySize)
5270 {
Jamie Madille0472f32018-11-27 16:32:45 -05005271 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Geoff Lang79b91402018-10-04 15:11:30 -04005272 return false;
5273 }
5274 break;
5275
Jamie Madillbe849e42017-05-02 15:49:00 -04005276 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005277 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005278 return false;
5279 }
5280
5281 if (length)
5282 {
5283 *length = 1;
5284 }
5285 return true;
5286}
5287
5288bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5289{
5290 if (length)
5291 {
5292 *length = 0;
5293 }
5294
5295 if (GetValidShader(context, shader) == nullptr)
5296 {
5297 return false;
5298 }
5299
5300 switch (pname)
5301 {
5302 case GL_SHADER_TYPE:
5303 case GL_DELETE_STATUS:
5304 case GL_COMPILE_STATUS:
5305 case GL_INFO_LOG_LENGTH:
5306 case GL_SHADER_SOURCE_LENGTH:
5307 break;
5308
5309 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5310 if (!context->getExtensions().translatedShaderSource)
5311 {
Jamie Madille0472f32018-11-27 16:32:45 -05005312 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005313 return false;
5314 }
5315 break;
5316
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005317 case GL_COMPLETION_STATUS_KHR:
5318 if (!context->getExtensions().parallelShaderCompile)
5319 {
Jamie Madille0472f32018-11-27 16:32:45 -05005320 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005321 return false;
5322 }
5323 break;
5324
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005326 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005327 return false;
5328 }
5329
5330 if (length)
5331 {
5332 *length = 1;
5333 }
5334 return true;
5335}
5336
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005337bool ValidateGetTexParameterBase(Context *context,
5338 TextureType target,
5339 GLenum pname,
5340 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005341{
5342 if (length)
5343 {
5344 *length = 0;
5345 }
5346
5347 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5348 {
Jamie Madille0472f32018-11-27 16:32:45 -05005349 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005350 return false;
5351 }
5352
5353 if (context->getTargetTexture(target) == nullptr)
5354 {
5355 // Should only be possible for external textures
Jamie Madille0472f32018-11-27 16:32:45 -05005356 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005357 return false;
5358 }
5359
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005360 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5361 {
Jamie Madille0472f32018-11-27 16:32:45 -05005362 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005363 return false;
5364 }
5365
Jamie Madillbe849e42017-05-02 15:49:00 -04005366 switch (pname)
5367 {
5368 case GL_TEXTURE_MAG_FILTER:
5369 case GL_TEXTURE_MIN_FILTER:
5370 case GL_TEXTURE_WRAP_S:
5371 case GL_TEXTURE_WRAP_T:
5372 break;
5373
5374 case GL_TEXTURE_USAGE_ANGLE:
5375 if (!context->getExtensions().textureUsage)
5376 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005377 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 return false;
5379 }
5380 break;
5381
5382 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005383 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005384 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005385 return false;
5386 }
5387 break;
5388
5389 case GL_TEXTURE_IMMUTABLE_FORMAT:
5390 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5391 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005392 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395 break;
5396
5397 case GL_TEXTURE_WRAP_R:
5398 case GL_TEXTURE_IMMUTABLE_LEVELS:
5399 case GL_TEXTURE_SWIZZLE_R:
5400 case GL_TEXTURE_SWIZZLE_G:
5401 case GL_TEXTURE_SWIZZLE_B:
5402 case GL_TEXTURE_SWIZZLE_A:
5403 case GL_TEXTURE_BASE_LEVEL:
5404 case GL_TEXTURE_MAX_LEVEL:
5405 case GL_TEXTURE_MIN_LOD:
5406 case GL_TEXTURE_MAX_LOD:
5407 case GL_TEXTURE_COMPARE_MODE:
5408 case GL_TEXTURE_COMPARE_FUNC:
5409 if (context->getClientMajorVersion() < 3)
5410 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005411 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Jamie Madillbe849e42017-05-02 15:49:00 -04005412 return false;
5413 }
5414 break;
5415
5416 case GL_TEXTURE_SRGB_DECODE_EXT:
5417 if (!context->getExtensions().textureSRGBDecode)
5418 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005419 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005420 return false;
5421 }
5422 break;
5423
Yunchao Hebacaa712018-01-30 14:01:39 +08005424 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5425 if (context->getClientVersion() < Version(3, 1))
5426 {
Jamie Madille0472f32018-11-27 16:32:45 -05005427 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Yunchao Hebacaa712018-01-30 14:01:39 +08005428 return false;
5429 }
5430 break;
5431
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005432 case GL_GENERATE_MIPMAP:
5433 case GL_TEXTURE_CROP_RECT_OES:
5434 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5435 // after GL_OES_draw_texture functionality implemented
5436 if (context->getClientMajorVersion() > 1)
5437 {
Jamie Madille0472f32018-11-27 16:32:45 -05005438 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005439 return false;
5440 }
5441 break;
Geoff Lang79b91402018-10-04 15:11:30 -04005442
5443 case GL_MEMORY_SIZE_ANGLE:
5444 if (!context->getExtensions().memorySize)
5445 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005446 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang79b91402018-10-04 15:11:30 -04005447 return false;
5448 }
5449 break;
5450
Till Rathmannb8543632018-10-02 19:46:14 +02005451 case GL_TEXTURE_BORDER_COLOR:
5452 if (!context->getExtensions().textureBorderClamp)
5453 {
Jamie Madille0472f32018-11-27 16:32:45 -05005454 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02005455 return false;
5456 }
5457 break;
5458
Jamie Madillbe849e42017-05-02 15:49:00 -04005459 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005460 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005461 return false;
5462 }
5463
5464 if (length)
5465 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005466 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 }
5468 return true;
5469}
5470
5471bool ValidateGetVertexAttribBase(Context *context,
5472 GLuint index,
5473 GLenum pname,
5474 GLsizei *length,
5475 bool pointer,
5476 bool pureIntegerEntryPoint)
5477{
5478 if (length)
5479 {
5480 *length = 0;
5481 }
5482
5483 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5484 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005485 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005486 return false;
5487 }
5488
5489 if (index >= context->getCaps().maxVertexAttributes)
5490 {
Jamie Madille0472f32018-11-27 16:32:45 -05005491 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 return false;
5493 }
5494
5495 if (pointer)
5496 {
5497 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5498 {
Jamie Madille0472f32018-11-27 16:32:45 -05005499 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005500 return false;
5501 }
5502 }
5503 else
5504 {
5505 switch (pname)
5506 {
5507 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5508 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5509 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5510 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5511 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5512 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5513 case GL_CURRENT_VERTEX_ATTRIB:
5514 break;
5515
5516 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5517 static_assert(
5518 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5519 "ANGLE extension enums not equal to GL enums.");
5520 if (context->getClientMajorVersion() < 3 &&
5521 !context->getExtensions().instancedArrays)
5522 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005523 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005524 return false;
5525 }
5526 break;
5527
5528 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5529 if (context->getClientMajorVersion() < 3)
5530 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005531 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005532 return false;
5533 }
5534 break;
5535
5536 case GL_VERTEX_ATTRIB_BINDING:
5537 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5538 if (context->getClientVersion() < ES_3_1)
5539 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005540 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005541 return false;
5542 }
5543 break;
5544
5545 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005546 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005547 return false;
5548 }
5549 }
5550
5551 if (length)
5552 {
5553 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5554 {
5555 *length = 4;
5556 }
5557 else
5558 {
5559 *length = 1;
5560 }
5561 }
5562
5563 return true;
5564}
5565
Jamie Madill4928b7c2017-06-20 12:57:39 -04005566bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 GLint x,
5568 GLint y,
5569 GLsizei width,
5570 GLsizei height,
5571 GLenum format,
5572 GLenum type,
5573 GLsizei bufSize,
5574 GLsizei *length,
5575 GLsizei *columns,
5576 GLsizei *rows,
5577 void *pixels)
5578{
5579 if (length != nullptr)
5580 {
5581 *length = 0;
5582 }
5583 if (rows != nullptr)
5584 {
5585 *rows = 0;
5586 }
5587 if (columns != nullptr)
5588 {
5589 *columns = 0;
5590 }
5591
5592 if (width < 0 || height < 0)
5593 {
Jamie Madille0472f32018-11-27 16:32:45 -05005594 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005595 return false;
5596 }
5597
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005598 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005599
Jamie Madill427064d2018-04-13 16:20:34 -04005600 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005601 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005602 return false;
5603 }
5604
Jamie Madille98b1b52018-03-08 09:47:23 -05005605 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005606 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005607 return false;
5608 }
5609
Jamie Madill690c8eb2018-03-12 15:20:03 -04005610 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005611 ASSERT(framebuffer);
5612
5613 if (framebuffer->getReadBufferState() == GL_NONE)
5614 {
Jamie Madille0472f32018-11-27 16:32:45 -05005615 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005616 return false;
5617 }
5618
5619 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5620 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5621 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5622 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5623 // situation is an application error that would lead to a crash in ANGLE.
5624 if (readBuffer == nullptr)
5625 {
Jamie Madille0472f32018-11-27 16:32:45 -05005626 context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005627 return false;
5628 }
5629
Martin Radev28031682017-07-28 14:47:56 +03005630 // ANGLE_multiview, Revision 1:
5631 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005632 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5633 // in the current read framebuffer is more than one.
5634 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005635 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005636 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
Martin Radev28031682017-07-28 14:47:56 +03005637 return false;
5638 }
5639
Geoff Lang280ba992017-04-18 16:30:58 -04005640 if (context->getExtensions().webglCompatibility)
5641 {
5642 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5643 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5644 // and type before validating the combination of format and type. However, the
5645 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5646 // verifies that GL_INVALID_OPERATION is generated.
5647 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5648 // dEQP/WebGL.
5649 if (!ValidReadPixelsFormatEnum(context, format))
5650 {
Jamie Madille0472f32018-11-27 16:32:45 -05005651 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005652 return false;
5653 }
5654
5655 if (!ValidReadPixelsTypeEnum(context, type))
5656 {
Jamie Madille0472f32018-11-27 16:32:45 -05005657 context->validationError(GL_INVALID_ENUM, kInvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005658 return false;
5659 }
5660 }
5661
Jamie Madill690c8eb2018-03-12 15:20:03 -04005662 GLenum currentFormat = GL_NONE;
5663 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5664
5665 GLenum currentType = GL_NONE;
5666 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5667
Jamie Madillbe849e42017-05-02 15:49:00 -04005668 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5669
5670 bool validFormatTypeCombination =
5671 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5672
5673 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5674 {
Jamie Madille0472f32018-11-27 16:32:45 -05005675 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005676 return false;
5677 }
5678
5679 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005680 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005681 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5682 {
5683 // ...the buffer object's data store is currently mapped.
Jamie Madillc3e37312018-11-30 15:25:39 -05005684 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
Jamie Madillbe849e42017-05-02 15:49:00 -04005685 return false;
5686 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005687 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5688 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5689 {
Jamie Madille0472f32018-11-27 16:32:45 -05005690 context->validationError(GL_INVALID_OPERATION, kPixelPackBufferBoundForTransformFeedback);
James Darpiniane8a93c62018-01-04 18:02:24 -08005691 return false;
5692 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005693
5694 // .. the data would be packed to the buffer object such that the memory writes required
5695 // would exceed the data store size.
5696 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005697 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005698 const auto &pack = context->getGLState().getPackState();
5699
Jamie Madillca2ff382018-07-11 09:01:17 -04005700 GLuint endByte = 0;
5701 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005702 {
Jamie Madille0472f32018-11-27 16:32:45 -05005703 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005704 return false;
5705 }
5706
Jamie Madillbe849e42017-05-02 15:49:00 -04005707 if (bufSize >= 0)
5708 {
5709 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5710 {
Jamie Madille0472f32018-11-27 16:32:45 -05005711 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005712 return false;
5713 }
5714 }
5715
5716 if (pixelPackBuffer != nullptr)
5717 {
5718 CheckedNumeric<size_t> checkedEndByte(endByte);
5719 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5720 checkedEndByte += checkedOffset;
5721
5722 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5723 {
5724 // Overflow past the end of the buffer
Jamie Madille0472f32018-11-27 16:32:45 -05005725 context->validationError(GL_INVALID_OPERATION, kParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005726 return false;
5727 }
5728 }
5729
5730 if (pixelPackBuffer == nullptr && length != nullptr)
5731 {
5732 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5733 {
Jamie Madille0472f32018-11-27 16:32:45 -05005734 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005735 return false;
5736 }
5737
5738 *length = static_cast<GLsizei>(endByte);
5739 }
5740
Geoff Langa953b522018-02-21 16:56:23 -05005741 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005742 angle::CheckedNumeric<int> clippedExtent(length);
5743 if (start < 0)
5744 {
5745 // "subtract" the area that is less than 0
5746 clippedExtent += start;
5747 }
5748
Geoff Langa953b522018-02-21 16:56:23 -05005749 angle::CheckedNumeric<int> readExtent = start;
5750 readExtent += length;
5751 if (!readExtent.IsValid())
5752 {
5753 return false;
5754 }
5755
5756 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005757 {
5758 // Subtract the region to the right of the read buffer
5759 clippedExtent -= (readExtent - bufferSize);
5760 }
5761
5762 if (!clippedExtent.IsValid())
5763 {
Geoff Langa953b522018-02-21 16:56:23 -05005764 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005765 }
5766
Geoff Langa953b522018-02-21 16:56:23 -05005767 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5768 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005769 };
5770
Geoff Langa953b522018-02-21 16:56:23 -05005771 GLsizei writtenColumns = 0;
5772 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5773 {
Jamie Madille0472f32018-11-27 16:32:45 -05005774 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langa953b522018-02-21 16:56:23 -05005775 return false;
5776 }
5777
5778 GLsizei writtenRows = 0;
5779 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5780 {
Jamie Madille0472f32018-11-27 16:32:45 -05005781 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langa953b522018-02-21 16:56:23 -05005782 return false;
5783 }
5784
Jamie Madillbe849e42017-05-02 15:49:00 -04005785 if (columns != nullptr)
5786 {
Geoff Langa953b522018-02-21 16:56:23 -05005787 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005788 }
5789
5790 if (rows != nullptr)
5791 {
Geoff Langa953b522018-02-21 16:56:23 -05005792 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005793 }
5794
5795 return true;
5796}
5797
5798template <typename ParamType>
5799bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005800 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 GLenum pname,
5802 GLsizei bufSize,
Till Rathmannb8543632018-10-02 19:46:14 +02005803 bool vectorParams,
Jamie Madillbe849e42017-05-02 15:49:00 -04005804 const ParamType *params)
5805{
5806 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5807 {
Jamie Madille0472f32018-11-27 16:32:45 -05005808 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005809 return false;
5810 }
5811
5812 if (context->getTargetTexture(target) == nullptr)
5813 {
5814 // Should only be possible for external textures
Jamie Madille0472f32018-11-27 16:32:45 -05005815 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005816 return false;
5817 }
5818
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005819 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005820 if (bufSize >= 0 && bufSize < minBufSize)
5821 {
Jamie Madille0472f32018-11-27 16:32:45 -05005822 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005823 return false;
5824 }
5825
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005826 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5827 {
Jamie Madille0472f32018-11-27 16:32:45 -05005828 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005829 return false;
5830 }
5831
Jamie Madillbe849e42017-05-02 15:49:00 -04005832 switch (pname)
5833 {
5834 case GL_TEXTURE_WRAP_R:
5835 case GL_TEXTURE_SWIZZLE_R:
5836 case GL_TEXTURE_SWIZZLE_G:
5837 case GL_TEXTURE_SWIZZLE_B:
5838 case GL_TEXTURE_SWIZZLE_A:
5839 case GL_TEXTURE_BASE_LEVEL:
5840 case GL_TEXTURE_MAX_LEVEL:
5841 case GL_TEXTURE_COMPARE_MODE:
5842 case GL_TEXTURE_COMPARE_FUNC:
5843 case GL_TEXTURE_MIN_LOD:
5844 case GL_TEXTURE_MAX_LOD:
5845 if (context->getClientMajorVersion() < 3)
5846 {
Jamie Madille0472f32018-11-27 16:32:45 -05005847 context->validationError(GL_INVALID_ENUM, kES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005848 return false;
5849 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005850 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005851 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005852 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005853 return false;
5854 }
5855 break;
5856
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005857 case GL_GENERATE_MIPMAP:
5858 case GL_TEXTURE_CROP_RECT_OES:
5859 if (context->getClientMajorVersion() > 1)
5860 {
Jamie Madille0472f32018-11-27 16:32:45 -05005861 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005862 return false;
5863 }
5864 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005865 default:
5866 break;
5867 }
5868
Olli Etuahod310a432018-08-24 15:40:23 +03005869 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005870 {
5871 switch (pname)
5872 {
5873 case GL_TEXTURE_MIN_FILTER:
5874 case GL_TEXTURE_MAG_FILTER:
5875 case GL_TEXTURE_WRAP_S:
5876 case GL_TEXTURE_WRAP_T:
5877 case GL_TEXTURE_WRAP_R:
5878 case GL_TEXTURE_MIN_LOD:
5879 case GL_TEXTURE_MAX_LOD:
5880 case GL_TEXTURE_COMPARE_MODE:
5881 case GL_TEXTURE_COMPARE_FUNC:
Till Rathmannb8543632018-10-02 19:46:14 +02005882 case GL_TEXTURE_BORDER_COLOR:
Jamie Madillc3e37312018-11-30 15:25:39 -05005883 context->validationError(GL_INVALID_ENUM, kInvalidPname);
JiangYizhou4cff8d62017-07-06 14:54:09 +08005884 return false;
5885 }
5886 }
5887
Jamie Madillbe849e42017-05-02 15:49:00 -04005888 switch (pname)
5889 {
5890 case GL_TEXTURE_WRAP_S:
5891 case GL_TEXTURE_WRAP_T:
5892 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005893 {
5894 bool restrictedWrapModes =
5895 target == TextureType::External || target == TextureType::Rectangle;
5896 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005897 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005898 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005899 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005900 }
5901 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005902
5903 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005904 {
5905 bool restrictedMinFilter =
5906 target == TextureType::External || target == TextureType::Rectangle;
5907 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005908 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005909 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005910 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005911 }
5912 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005913
5914 case GL_TEXTURE_MAG_FILTER:
5915 if (!ValidateTextureMagFilterValue(context, params))
5916 {
5917 return false;
5918 }
5919 break;
5920
5921 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005922 if (!context->getExtensions().textureUsage)
5923 {
Jamie Madille0472f32018-11-27 16:32:45 -05005924 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang91ab54b2017-10-30 15:12:42 -04005925 return false;
5926 }
5927
Jamie Madillbe849e42017-05-02 15:49:00 -04005928 switch (ConvertToGLenum(params[0]))
5929 {
5930 case GL_NONE:
5931 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5932 break;
5933
5934 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005935 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005936 return false;
5937 }
5938 break;
5939
5940 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005941 {
5942 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5943 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005944 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005945 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005946 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005947 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5948 }
5949 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005950
5951 case GL_TEXTURE_MIN_LOD:
5952 case GL_TEXTURE_MAX_LOD:
5953 // any value is permissible
5954 break;
5955
5956 case GL_TEXTURE_COMPARE_MODE:
5957 if (!ValidateTextureCompareModeValue(context, params))
5958 {
5959 return false;
5960 }
5961 break;
5962
5963 case GL_TEXTURE_COMPARE_FUNC:
5964 if (!ValidateTextureCompareFuncValue(context, params))
5965 {
5966 return false;
5967 }
5968 break;
5969
5970 case GL_TEXTURE_SWIZZLE_R:
5971 case GL_TEXTURE_SWIZZLE_G:
5972 case GL_TEXTURE_SWIZZLE_B:
5973 case GL_TEXTURE_SWIZZLE_A:
5974 switch (ConvertToGLenum(params[0]))
5975 {
5976 case GL_RED:
5977 case GL_GREEN:
5978 case GL_BLUE:
5979 case GL_ALPHA:
5980 case GL_ZERO:
5981 case GL_ONE:
5982 break;
5983
5984 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005985 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005986 return false;
5987 }
5988 break;
5989
5990 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005991 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005992 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005993 context->validationError(GL_INVALID_VALUE, kBaseLevelNegative);
Jamie Madillbe849e42017-05-02 15:49:00 -04005994 return false;
5995 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005996 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005997 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005998 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04005999 return false;
6000 }
Olli Etuahod310a432018-08-24 15:40:23 +03006001 if ((target == TextureType::_2DMultisample ||
6002 target == TextureType::_2DMultisampleArray) &&
6003 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006004 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006005 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
JiangYizhou4cff8d62017-07-06 14:54:09 +08006006 return false;
6007 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006008 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006009 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006010 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006011 return false;
6012 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006013 break;
6014
6015 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006016 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006017 {
Jamie Madille0472f32018-11-27 16:32:45 -05006018 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006019 return false;
6020 }
6021 break;
6022
6023 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6024 if (context->getClientVersion() < Version(3, 1))
6025 {
Jamie Madille0472f32018-11-27 16:32:45 -05006026 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006027 return false;
6028 }
6029 switch (ConvertToGLenum(params[0]))
6030 {
6031 case GL_DEPTH_COMPONENT:
6032 case GL_STENCIL_INDEX:
6033 break;
6034
6035 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006036 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006037 return false;
6038 }
6039 break;
6040
6041 case GL_TEXTURE_SRGB_DECODE_EXT:
6042 if (!ValidateTextureSRGBDecodeValue(context, params))
6043 {
6044 return false;
6045 }
6046 break;
6047
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006048 case GL_GENERATE_MIPMAP:
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006049 if (context->getClientMajorVersion() > 1)
6050 {
Jamie Madille0472f32018-11-27 16:32:45 -05006051 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006052 return false;
6053 }
6054 break;
Till Rathmannb8543632018-10-02 19:46:14 +02006055
6056 case GL_TEXTURE_CROP_RECT_OES:
6057 if (context->getClientMajorVersion() > 1)
6058 {
Jamie Madille0472f32018-11-27 16:32:45 -05006059 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Till Rathmannb8543632018-10-02 19:46:14 +02006060 return false;
6061 }
6062 if (!vectorParams)
6063 {
Jamie Madille0472f32018-11-27 16:32:45 -05006064 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006065 return false;
6066 }
6067 break;
6068
6069 case GL_TEXTURE_BORDER_COLOR:
6070 if (!context->getExtensions().textureBorderClamp)
6071 {
Jamie Madille0472f32018-11-27 16:32:45 -05006072 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006073 return false;
6074 }
6075 if (!vectorParams)
6076 {
Jamie Madille0472f32018-11-27 16:32:45 -05006077 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006078 return false;
6079 }
6080 break;
6081
Jamie Madillbe849e42017-05-02 15:49:00 -04006082 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006083 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006084 return false;
6085 }
6086
6087 return true;
6088}
6089
Till Rathmannb8543632018-10-02 19:46:14 +02006090template bool ValidateTexParameterBase(Context *,
6091 TextureType,
6092 GLenum,
6093 GLsizei,
6094 bool,
6095 const GLfloat *);
6096template bool ValidateTexParameterBase(Context *,
6097 TextureType,
6098 GLenum,
6099 GLsizei,
6100 bool,
6101 const GLint *);
6102template bool ValidateTexParameterBase(Context *,
6103 TextureType,
6104 GLenum,
6105 GLsizei,
6106 bool,
6107 const GLuint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006108
Jamie Madill5b772312018-03-08 20:28:32 -05006109bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006110{
6111 if (index >= MAX_VERTEX_ATTRIBS)
6112 {
Jamie Madille0472f32018-11-27 16:32:45 -05006113 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Jamie Madill12e957f2017-08-26 21:42:26 -04006114 return false;
6115 }
6116
6117 return true;
6118}
6119
6120bool ValidateGetActiveUniformBlockivBase(Context *context,
6121 GLuint program,
6122 GLuint uniformBlockIndex,
6123 GLenum pname,
6124 GLsizei *length)
6125{
6126 if (length)
6127 {
6128 *length = 0;
6129 }
6130
6131 if (context->getClientMajorVersion() < 3)
6132 {
Jamie Madille0472f32018-11-27 16:32:45 -05006133 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill12e957f2017-08-26 21:42:26 -04006134 return false;
6135 }
6136
6137 Program *programObject = GetValidProgram(context, program);
6138 if (!programObject)
6139 {
6140 return false;
6141 }
6142
6143 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6144 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006145 context->validationError(GL_INVALID_VALUE, kIndexExceedsActiveUniformBlockCount);
Jamie Madill12e957f2017-08-26 21:42:26 -04006146 return false;
6147 }
6148
6149 switch (pname)
6150 {
6151 case GL_UNIFORM_BLOCK_BINDING:
6152 case GL_UNIFORM_BLOCK_DATA_SIZE:
6153 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6154 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6155 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6156 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6157 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6158 break;
6159
6160 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006161 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill12e957f2017-08-26 21:42:26 -04006162 return false;
6163 }
6164
6165 if (length)
6166 {
6167 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6168 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006169 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006170 programObject->getUniformBlockByIndex(uniformBlockIndex);
6171 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6172 }
6173 else
6174 {
6175 *length = 1;
6176 }
6177 }
6178
6179 return true;
6180}
6181
Jamie Madill9696d072017-08-26 23:19:57 -04006182template <typename ParamType>
6183bool ValidateSamplerParameterBase(Context *context,
6184 GLuint sampler,
6185 GLenum pname,
6186 GLsizei bufSize,
Till Rathmannb8543632018-10-02 19:46:14 +02006187 bool vectorParams,
Jamie Madill9696d072017-08-26 23:19:57 -04006188 ParamType *params)
6189{
6190 if (context->getClientMajorVersion() < 3)
6191 {
Jamie Madille0472f32018-11-27 16:32:45 -05006192 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006193 return false;
6194 }
6195
6196 if (!context->isSampler(sampler))
6197 {
Jamie Madille0472f32018-11-27 16:32:45 -05006198 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
Jamie Madill9696d072017-08-26 23:19:57 -04006199 return false;
6200 }
6201
Till Rathmannb8543632018-10-02 19:46:14 +02006202 const GLsizei minBufSize = GetSamplerParameterCount(pname);
Jamie Madill9696d072017-08-26 23:19:57 -04006203 if (bufSize >= 0 && bufSize < minBufSize)
6204 {
Jamie Madille0472f32018-11-27 16:32:45 -05006205 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madill9696d072017-08-26 23:19:57 -04006206 return false;
6207 }
6208
6209 switch (pname)
6210 {
6211 case GL_TEXTURE_WRAP_S:
6212 case GL_TEXTURE_WRAP_T:
6213 case GL_TEXTURE_WRAP_R:
6214 if (!ValidateTextureWrapModeValue(context, params, false))
6215 {
6216 return false;
6217 }
6218 break;
6219
6220 case GL_TEXTURE_MIN_FILTER:
6221 if (!ValidateTextureMinFilterValue(context, params, false))
6222 {
6223 return false;
6224 }
6225 break;
6226
6227 case GL_TEXTURE_MAG_FILTER:
6228 if (!ValidateTextureMagFilterValue(context, params))
6229 {
6230 return false;
6231 }
6232 break;
6233
6234 case GL_TEXTURE_MIN_LOD:
6235 case GL_TEXTURE_MAX_LOD:
6236 // any value is permissible
6237 break;
6238
6239 case GL_TEXTURE_COMPARE_MODE:
6240 if (!ValidateTextureCompareModeValue(context, params))
6241 {
6242 return false;
6243 }
6244 break;
6245
6246 case GL_TEXTURE_COMPARE_FUNC:
6247 if (!ValidateTextureCompareFuncValue(context, params))
6248 {
6249 return false;
6250 }
6251 break;
6252
6253 case GL_TEXTURE_SRGB_DECODE_EXT:
6254 if (!ValidateTextureSRGBDecodeValue(context, params))
6255 {
6256 return false;
6257 }
6258 break;
6259
Luc Ferron1b1a8642018-01-23 15:12:01 -05006260 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6261 {
6262 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6263 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6264 {
6265 return false;
6266 }
6267 }
6268 break;
6269
Till Rathmannb8543632018-10-02 19:46:14 +02006270 case GL_TEXTURE_BORDER_COLOR:
6271 if (!context->getExtensions().textureBorderClamp)
6272 {
Jamie Madille0472f32018-11-27 16:32:45 -05006273 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006274 return false;
6275 }
6276 if (!vectorParams)
6277 {
Jamie Madille0472f32018-11-27 16:32:45 -05006278 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006279 return false;
6280 }
6281 break;
6282
Jamie Madill9696d072017-08-26 23:19:57 -04006283 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006284 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006285 return false;
6286 }
6287
6288 return true;
6289}
6290
Till Rathmannb8543632018-10-02 19:46:14 +02006291template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, bool, GLfloat *);
6292template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, bool, GLint *);
6293template bool ValidateSamplerParameterBase(Context *,
6294 GLuint,
6295 GLenum,
6296 GLsizei,
6297 bool,
6298 const GLuint *);
Jamie Madill9696d072017-08-26 23:19:57 -04006299
6300bool ValidateGetSamplerParameterBase(Context *context,
6301 GLuint sampler,
6302 GLenum pname,
6303 GLsizei *length)
6304{
6305 if (length)
6306 {
6307 *length = 0;
6308 }
6309
6310 if (context->getClientMajorVersion() < 3)
6311 {
Jamie Madille0472f32018-11-27 16:32:45 -05006312 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006313 return false;
6314 }
6315
6316 if (!context->isSampler(sampler))
6317 {
Jamie Madille0472f32018-11-27 16:32:45 -05006318 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
Jamie Madill9696d072017-08-26 23:19:57 -04006319 return false;
6320 }
6321
6322 switch (pname)
6323 {
6324 case GL_TEXTURE_WRAP_S:
6325 case GL_TEXTURE_WRAP_T:
6326 case GL_TEXTURE_WRAP_R:
6327 case GL_TEXTURE_MIN_FILTER:
6328 case GL_TEXTURE_MAG_FILTER:
6329 case GL_TEXTURE_MIN_LOD:
6330 case GL_TEXTURE_MAX_LOD:
6331 case GL_TEXTURE_COMPARE_MODE:
6332 case GL_TEXTURE_COMPARE_FUNC:
6333 break;
6334
Luc Ferron1b1a8642018-01-23 15:12:01 -05006335 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6336 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6337 {
6338 return false;
6339 }
6340 break;
6341
Jamie Madill9696d072017-08-26 23:19:57 -04006342 case GL_TEXTURE_SRGB_DECODE_EXT:
6343 if (!context->getExtensions().textureSRGBDecode)
6344 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006345 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006346 return false;
6347 }
6348 break;
6349
Till Rathmannb8543632018-10-02 19:46:14 +02006350 case GL_TEXTURE_BORDER_COLOR:
6351 if (!context->getExtensions().textureBorderClamp)
6352 {
Jamie Madille0472f32018-11-27 16:32:45 -05006353 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006354 return false;
6355 }
6356 break;
6357
Jamie Madill9696d072017-08-26 23:19:57 -04006358 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006359 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006360 return false;
6361 }
6362
6363 if (length)
6364 {
Till Rathmannb8543632018-10-02 19:46:14 +02006365 *length = GetSamplerParameterCount(pname);
Jamie Madill9696d072017-08-26 23:19:57 -04006366 }
6367 return true;
6368}
6369
6370bool ValidateGetInternalFormativBase(Context *context,
6371 GLenum target,
6372 GLenum internalformat,
6373 GLenum pname,
6374 GLsizei bufSize,
6375 GLsizei *numParams)
6376{
6377 if (numParams)
6378 {
6379 *numParams = 0;
6380 }
6381
6382 if (context->getClientMajorVersion() < 3)
6383 {
Jamie Madille0472f32018-11-27 16:32:45 -05006384 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006385 return false;
6386 }
6387
6388 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006389 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006390 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006391 context->validationError(GL_INVALID_ENUM, kFormatNotRenderable);
Jamie Madill9696d072017-08-26 23:19:57 -04006392 return false;
6393 }
6394
6395 switch (target)
6396 {
6397 case GL_RENDERBUFFER:
6398 break;
6399
6400 case GL_TEXTURE_2D_MULTISAMPLE:
Yizhou Jiang7818a852018-09-06 15:02:04 +08006401 if (context->getClientVersion() < ES_3_1 &&
6402 !context->getExtensions().textureMultisample)
Jamie Madill9696d072017-08-26 23:19:57 -04006403 {
Jamie Madill610640f2018-11-21 17:28:41 -05006404 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05006405 kMultisampleTextureExtensionOrES31Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006406 return false;
6407 }
6408 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006409 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6410 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006411 {
Jamie Madille0472f32018-11-27 16:32:45 -05006412 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
Olli Etuahod310a432018-08-24 15:40:23 +03006413 return false;
6414 }
6415 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006416 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006417 context->validationError(GL_INVALID_ENUM, kInvalidTarget);
Jamie Madill9696d072017-08-26 23:19:57 -04006418 return false;
6419 }
6420
6421 if (bufSize < 0)
6422 {
Jamie Madille0472f32018-11-27 16:32:45 -05006423 context->validationError(GL_INVALID_VALUE, kInsufficientBufferSize);
Jamie Madill9696d072017-08-26 23:19:57 -04006424 return false;
6425 }
6426
6427 GLsizei maxWriteParams = 0;
6428 switch (pname)
6429 {
6430 case GL_NUM_SAMPLE_COUNTS:
6431 maxWriteParams = 1;
6432 break;
6433
6434 case GL_SAMPLES:
6435 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6436 break;
6437
6438 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006439 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006440 return false;
6441 }
6442
6443 if (numParams)
6444 {
6445 // glGetInternalFormativ will not overflow bufSize
6446 *numParams = std::min(bufSize, maxWriteParams);
6447 }
6448
6449 return true;
6450}
6451
Jamie Madille98b1b52018-03-08 09:47:23 -05006452bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6453{
Jamie Madill427064d2018-04-13 16:20:34 -04006454 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006455 {
Jamie Madille0472f32018-11-27 16:32:45 -05006456 context->validationError(GL_INVALID_OPERATION, kInvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006457 return false;
6458 }
6459 return true;
6460}
6461
Lingfeng Yang038dd532018-03-29 17:31:52 -07006462bool ValidateMultitextureUnit(Context *context, GLenum texture)
6463{
6464 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6465 {
Jamie Madille0472f32018-11-27 16:32:45 -05006466 context->validationError(GL_INVALID_ENUM, kInvalidMultitextureUnit);
Lingfeng Yang038dd532018-03-29 17:31:52 -07006467 return false;
6468 }
6469 return true;
6470}
6471
Olli Etuahod310a432018-08-24 15:40:23 +03006472bool ValidateTexStorageMultisample(Context *context,
6473 TextureType target,
6474 GLsizei samples,
6475 GLint internalFormat,
6476 GLsizei width,
6477 GLsizei height)
6478{
6479 const Caps &caps = context->getCaps();
6480 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6481 static_cast<GLuint>(height) > caps.max2DTextureSize)
6482 {
Jamie Madille0472f32018-11-27 16:32:45 -05006483 context->validationError(GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
Olli Etuahod310a432018-08-24 15:40:23 +03006484 return false;
6485 }
6486
6487 if (samples == 0)
6488 {
Jamie Madille0472f32018-11-27 16:32:45 -05006489 context->validationError(GL_INVALID_VALUE, kSamplesZero);
Olli Etuahod310a432018-08-24 15:40:23 +03006490 return false;
6491 }
6492
6493 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6494 if (!formatCaps.textureAttachment)
6495 {
Jamie Madille0472f32018-11-27 16:32:45 -05006496 context->validationError(GL_INVALID_ENUM, kRenderableInternalFormat);
Olli Etuahod310a432018-08-24 15:40:23 +03006497 return false;
6498 }
6499
6500 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6501 // is one of the unsized base internalformats listed in table 8.11.
6502 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6503 if (formatInfo.internalFormat == GL_NONE)
6504 {
Jamie Madille0472f32018-11-27 16:32:45 -05006505 context->validationError(GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
Olli Etuahod310a432018-08-24 15:40:23 +03006506 return false;
6507 }
6508
6509 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6510 {
Jamie Madille0472f32018-11-27 16:32:45 -05006511 context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
Olli Etuahod310a432018-08-24 15:40:23 +03006512 return false;
6513 }
6514
6515 Texture *texture = context->getTargetTexture(target);
6516 if (!texture || texture->id() == 0)
6517 {
Jamie Madille0472f32018-11-27 16:32:45 -05006518 context->validationError(GL_INVALID_OPERATION, kZeroBoundToTarget);
Olli Etuahod310a432018-08-24 15:40:23 +03006519 return false;
6520 }
6521
6522 if (texture->getImmutableFormat())
6523 {
Jamie Madille0472f32018-11-27 16:32:45 -05006524 context->validationError(GL_INVALID_OPERATION, kImmutableTextureBound);
Olli Etuahod310a432018-08-24 15:40:23 +03006525 return false;
6526 }
6527 return true;
6528}
6529
Yizhou Jiang7818a852018-09-06 15:02:04 +08006530bool ValidateTexStorage2DMultisampleBase(Context *context,
6531 TextureType target,
6532 GLsizei samples,
6533 GLint internalFormat,
6534 GLsizei width,
6535 GLsizei height)
6536{
6537 if (target != TextureType::_2DMultisample)
6538 {
Jamie Madille0472f32018-11-27 16:32:45 -05006539 context->validationError(GL_INVALID_ENUM, kInvalidTarget);
Yizhou Jiang7818a852018-09-06 15:02:04 +08006540 return false;
6541 }
6542
6543 if (width < 1 || height < 1)
6544 {
Jamie Madille0472f32018-11-27 16:32:45 -05006545 context->validationError(GL_INVALID_VALUE, kTextureSizeTooSmall);
Yizhou Jiang7818a852018-09-06 15:02:04 +08006546 return false;
6547 }
6548
6549 return ValidateTexStorageMultisample(context, target, samples, internalFormat, width, height);
6550}
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006551
6552bool ValidateGetTexLevelParameterBase(Context *context,
6553 TextureTarget target,
6554 GLint level,
6555 GLenum pname,
6556 GLsizei *length)
6557{
6558
6559 if (length)
6560 {
6561 *length = 0;
6562 }
6563
6564 TextureType type = TextureTargetToType(target);
6565
6566 if (!ValidTexLevelDestinationTarget(context, type))
6567 {
Jamie Madille0472f32018-11-27 16:32:45 -05006568 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006569 return false;
6570 }
6571
6572 if (context->getTargetTexture(type) == nullptr)
6573 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006574 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006575 return false;
6576 }
6577
6578 if (!ValidMipLevel(context, type, level))
6579 {
Jamie Madille0472f32018-11-27 16:32:45 -05006580 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006581 return false;
6582 }
6583
6584 switch (pname)
6585 {
6586 case GL_TEXTURE_RED_TYPE:
6587 case GL_TEXTURE_GREEN_TYPE:
6588 case GL_TEXTURE_BLUE_TYPE:
6589 case GL_TEXTURE_ALPHA_TYPE:
6590 case GL_TEXTURE_DEPTH_TYPE:
6591 break;
6592 case GL_TEXTURE_RED_SIZE:
6593 case GL_TEXTURE_GREEN_SIZE:
6594 case GL_TEXTURE_BLUE_SIZE:
6595 case GL_TEXTURE_ALPHA_SIZE:
6596 case GL_TEXTURE_DEPTH_SIZE:
6597 case GL_TEXTURE_STENCIL_SIZE:
6598 case GL_TEXTURE_SHARED_SIZE:
6599 break;
6600 case GL_TEXTURE_INTERNAL_FORMAT:
6601 case GL_TEXTURE_WIDTH:
6602 case GL_TEXTURE_HEIGHT:
6603 case GL_TEXTURE_DEPTH:
6604 break;
6605 case GL_TEXTURE_SAMPLES:
6606 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
6607 break;
6608 case GL_TEXTURE_COMPRESSED:
6609 break;
6610 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006611 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006612 return false;
6613 }
6614
6615 if (length)
6616 {
6617 *length = 1;
6618 }
6619 return true;
6620}
Yizhou Jiang7310da32018-11-05 14:40:01 +08006621
6622bool ValidateGetMultisamplefvBase(Context *context, GLenum pname, GLuint index, GLfloat *val)
6623{
6624 if (pname != GL_SAMPLE_POSITION)
6625 {
6626 context->validationError(GL_INVALID_ENUM, kInvalidPname);
6627 return false;
6628 }
6629
6630 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
6631 GLint samples = framebuffer->getSamples(context);
6632
6633 if (index >= static_cast<GLuint>(samples))
6634 {
6635 context->validationError(GL_INVALID_VALUE, kIndexExceedsSamples);
6636 return false;
6637 }
6638
6639 return true;
6640}
6641
6642bool ValidateSampleMaskiBase(Context *context, GLuint maskNumber, GLbitfield mask)
6643{
6644 if (maskNumber >= context->getCaps().maxSampleMaskWords)
6645 {
6646 context->validationError(GL_INVALID_VALUE, kInvalidSampleMaskNumber);
6647 return false;
6648 }
6649
6650 return true;
6651}
Jamie Madillc29968b2016-01-20 11:17:23 -05006652} // namespace gl