blob: ed21c720f44241c9d625bf02fb64c592d1e622ba [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Lingfeng Yangf97641c2018-06-21 19:22:45 -070025#include "libANGLE/queryutils.h"
Jamie Madill778bf092018-11-14 09:54:36 -050026#include "libANGLE/validationES2_autogen.h"
27#include "libANGLE/validationES3_autogen.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29#include "common/mathutil.h"
30#include "common/utilities.h"
31
Jamie Madille2e406c2016-06-02 13:04:10 -040032using namespace angle;
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034namespace gl
35{
Jamie Madille0472f32018-11-27 16:32:45 -050036using namespace err;
37
Jamie Madill1ca74672015-07-21 15:14:11 -040038namespace
39{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050040bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
41{
42 // List of compressed format that require that the texture size is smaller than or a multiple of
43 // the compressed block size.
44 switch (internalFormat)
45 {
46 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
47 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
49 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
50 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
52 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
53 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
54 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
55 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
58 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
59 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
60 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Olli Etuahof2ed2992018-10-04 13:54:42 +030061 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
62 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
63 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
64 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
Luc Ferron9dbaeba2018-02-01 07:26:59 -050065 return true;
jchen10a99ed552017-09-22 08:10:32 +080066
Luc Ferron9dbaeba2018-02-01 07:26:59 -050067 default:
68 return false;
69 }
70}
71bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
72{
73 // Compressed sub textures have additional formats that requires exact size.
74 // ES 3.1, Section 8.7, Page 171
75 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
76 IsETC2EACFormat(internalFormat);
77}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030078
79bool DifferenceCanOverflow(GLint a, GLint b)
80{
81 CheckedNumeric<GLint> checkedA(a);
82 checkedA -= b;
83 // Use negation to make sure that the difference can't overflow regardless of the order.
84 checkedA = -checkedA;
85 return !checkedA.IsValid();
86}
87
Jamie Madill16e28fd2018-09-12 11:03:05 -040088bool ValidateDrawAttribsImpl(Context *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040089{
Jamie Madill51af38b2018-04-15 08:50:56 -040090 // If we're drawing zero vertices, we have enough data.
Jamie Madill2da53562018-08-01 11:34:47 -040091 ASSERT(primcount > 0);
Jamie Madill51af38b2018-04-15 08:50:56 -040092
Jamie Madill88602e62018-08-08 12:49:30 -040093 // An overflow can happen when adding the offset. Check against a special constant.
94 if (context->getStateCache().getNonInstancedVertexElementLimit() ==
95 VertexAttribute::kIntegerOverflow ||
96 context->getStateCache().getInstancedVertexElementLimit() ==
97 VertexAttribute::kIntegerOverflow)
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040098 {
Jamie Madille0472f32018-11-27 16:32:45 -050099 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400100 return false;
101 }
102
103 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
104 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
Jamie Madille0472f32018-11-27 16:32:45 -0500105 context->validationError(GL_INVALID_OPERATION, kInsufficientVertexBufferSize);
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400106 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400107}
108
Jamie Madill16e28fd2018-09-12 11:03:05 -0400109ANGLE_INLINE bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
110{
111 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
112 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
113 {
114 return true;
115 }
116 else
117 {
118 return ValidateDrawAttribsImpl(context, primcount, maxVertex);
119 }
120}
121
Jamie Madill5b772312018-03-08 20:28:32 -0500122bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400123{
124 switch (type)
125 {
126 // Types referenced in Table 3.4 of the ES 2.0.25 spec
127 case GL_UNSIGNED_BYTE:
128 case GL_UNSIGNED_SHORT_4_4_4_4:
129 case GL_UNSIGNED_SHORT_5_5_5_1:
130 case GL_UNSIGNED_SHORT_5_6_5:
131 return context->getClientVersion() >= ES_2_0;
132
133 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
134 case GL_BYTE:
135 case GL_INT:
136 case GL_SHORT:
137 case GL_UNSIGNED_INT:
138 case GL_UNSIGNED_INT_10F_11F_11F_REV:
139 case GL_UNSIGNED_INT_24_8:
140 case GL_UNSIGNED_INT_2_10_10_10_REV:
141 case GL_UNSIGNED_INT_5_9_9_9_REV:
142 case GL_UNSIGNED_SHORT:
143 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
144 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
145 return context->getClientVersion() >= ES_3_0;
146
147 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400148 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
149 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400150
151 case GL_HALF_FLOAT:
152 return context->getClientVersion() >= ES_3_0 ||
153 context->getExtensions().textureHalfFloat;
154
155 case GL_HALF_FLOAT_OES:
156 return context->getExtensions().colorBufferHalfFloat;
157
158 default:
159 return false;
160 }
161}
162
Jamie Madill5b772312018-03-08 20:28:32 -0500163bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400164{
165 switch (format)
166 {
167 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
168 case GL_RGBA:
169 case GL_RGB:
170 case GL_ALPHA:
171 return context->getClientVersion() >= ES_2_0;
172
173 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
174 case GL_RG:
175 case GL_RED:
176 case GL_RGBA_INTEGER:
177 case GL_RGB_INTEGER:
178 case GL_RG_INTEGER:
179 case GL_RED_INTEGER:
180 return context->getClientVersion() >= ES_3_0;
181
182 case GL_SRGB_ALPHA_EXT:
183 case GL_SRGB_EXT:
184 return context->getExtensions().sRGB;
185
186 case GL_BGRA_EXT:
187 return context->getExtensions().readFormatBGRA;
188
189 default:
190 return false;
191 }
192}
193
Jamie Madill5b772312018-03-08 20:28:32 -0500194bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400195 GLenum framebufferComponentType,
196 GLenum format,
197 GLenum type)
198{
199 switch (framebufferComponentType)
200 {
201 case GL_UNSIGNED_NORMALIZED:
202 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
203 // ReadPixels with BGRA even if the extension is not present
204 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
205 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
206 type == GL_UNSIGNED_BYTE);
207
208 case GL_SIGNED_NORMALIZED:
209 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
210
211 case GL_INT:
212 return (format == GL_RGBA_INTEGER && type == GL_INT);
213
214 case GL_UNSIGNED_INT:
215 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
216
217 case GL_FLOAT:
218 return (format == GL_RGBA && type == GL_FLOAT);
219
220 default:
221 UNREACHABLE();
222 return false;
223 }
224}
225
Geoff Langc1984ed2016-10-07 12:41:00 -0400226template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400227bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400228{
229 switch (ConvertToGLenum(params[0]))
230 {
231 case GL_CLAMP_TO_EDGE:
232 break;
233
Till Rathmannb8543632018-10-02 19:46:14 +0200234 case GL_CLAMP_TO_BORDER:
235 if (!context->getExtensions().textureBorderClamp)
236 {
Jamie Madille0472f32018-11-27 16:32:45 -0500237 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +0200238 return false;
239 }
240 break;
241
Geoff Langc1984ed2016-10-07 12:41:00 -0400242 case GL_REPEAT:
243 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400244 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400245 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400246 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Jamie Madille0472f32018-11-27 16:32:45 -0500247 context->validationError(GL_INVALID_ENUM, kInvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400248 return false;
249 }
250 break;
251
252 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500253 context->validationError(GL_INVALID_ENUM, kInvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400254 return false;
255 }
256
257 return true;
258}
259
260template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400261bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400262{
263 switch (ConvertToGLenum(params[0]))
264 {
265 case GL_NEAREST:
266 case GL_LINEAR:
267 break;
268
269 case GL_NEAREST_MIPMAP_NEAREST:
270 case GL_LINEAR_MIPMAP_NEAREST:
271 case GL_NEAREST_MIPMAP_LINEAR:
272 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400273 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400274 {
275 // OES_EGL_image_external specifies this error.
Jamie Madille0472f32018-11-27 16:32:45 -0500276 context->validationError(GL_INVALID_ENUM, kInvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400277 return false;
278 }
279 break;
280
281 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500282 context->validationError(GL_INVALID_ENUM, kInvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400283 return false;
284 }
285
286 return true;
287}
288
289template <typename ParamType>
290bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
291{
292 switch (ConvertToGLenum(params[0]))
293 {
294 case GL_NEAREST:
295 case GL_LINEAR:
296 break;
297
298 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500299 context->validationError(GL_INVALID_ENUM, kInvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400300 return false;
301 }
302
303 return true;
304}
305
306template <typename ParamType>
307bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
308{
309 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
310 switch (ConvertToGLenum(params[0]))
311 {
312 case GL_NONE:
313 case GL_COMPARE_REF_TO_TEXTURE:
314 break;
315
316 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500317 context->validationError(GL_INVALID_ENUM, kUnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400318 return false;
319 }
320
321 return true;
322}
323
324template <typename ParamType>
325bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
326{
327 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
328 switch (ConvertToGLenum(params[0]))
329 {
330 case GL_LEQUAL:
331 case GL_GEQUAL:
332 case GL_LESS:
333 case GL_GREATER:
334 case GL_EQUAL:
335 case GL_NOTEQUAL:
336 case GL_ALWAYS:
337 case GL_NEVER:
338 break;
339
340 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500341 context->validationError(GL_INVALID_ENUM, kUnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400342 return false;
343 }
344
345 return true;
346}
347
348template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700349bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
350{
351 if (!context->getExtensions().textureSRGBDecode)
352 {
Jamie Madille0472f32018-11-27 16:32:45 -0500353 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700354 return false;
355 }
356
357 switch (ConvertToGLenum(params[0]))
358 {
359 case GL_DECODE_EXT:
360 case GL_SKIP_DECODE_EXT:
361 break;
362
363 default:
Jamie Madille0472f32018-11-27 16:32:45 -0500364 context->validationError(GL_INVALID_ENUM, kUnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700365 return false;
366 }
367
368 return true;
369}
370
Luc Ferron1b1a8642018-01-23 15:12:01 -0500371bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
372{
373 if (!context->getExtensions().textureFilterAnisotropic)
374 {
Jamie Madille0472f32018-11-27 16:32:45 -0500375 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Luc Ferron1b1a8642018-01-23 15:12:01 -0500376 return false;
377 }
378
379 return true;
380}
381
382bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
383{
384 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
385 {
386 return false;
387 }
388
389 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
390
391 if (paramValue < 1 || paramValue > largest)
392 {
Jamie Madille0472f32018-11-27 16:32:45 -0500393 context->validationError(GL_INVALID_VALUE, kOutsideOfBounds);
Luc Ferron1b1a8642018-01-23 15:12:01 -0500394 return false;
395 }
396
397 return true;
398}
399
Jamie Madill5b772312018-03-08 20:28:32 -0500400bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400401{
Jamie Madill785e8a02018-10-04 17:42:00 -0400402 const Program *program = context->getGLState().getLinkedProgram(context);
Geoff Lange0cff192017-05-30 13:04:56 -0400403 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
404
Jamie Madille7d80f32018-08-08 15:49:23 -0400405 return ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
406 framebuffer->getDrawBufferTypeMask().to_ulong(),
407 program->getActiveOutputVariables().to_ulong(),
408 framebuffer->getDrawBufferMask().to_ulong());
Geoff Lange0cff192017-05-30 13:04:56 -0400409}
410
Jamie Madill5b772312018-03-08 20:28:32 -0500411bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400412{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700413 const auto &glState = context->getGLState();
Jamie Madill785e8a02018-10-04 17:42:00 -0400414 const Program *program = context->getGLState().getLinkedProgram(context);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400415 const VertexArray *vao = context->getGLState().getVertexArray();
416
Brandon Jonesc405ae72017-12-06 14:15:03 -0800417 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
418 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
419 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
420
421 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
422 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
423 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
424
Jamie Madille7d80f32018-08-08 15:49:23 -0400425 return ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(),
426 vaoAttribTypeBits, program->getAttributesMask().to_ulong(),
427 0xFFFF);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400428}
429
Jamie Madill493f9572018-05-24 19:52:15 -0400430bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
431 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800432{
433 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400434 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800435 {
Jamie Madill493f9572018-05-24 19:52:15 -0400436 case PrimitiveMode::Points:
437 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
438 case PrimitiveMode::Lines:
439 case PrimitiveMode::LineStrip:
440 case PrimitiveMode::LineLoop:
441 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
442 case PrimitiveMode::LinesAdjacency:
443 case PrimitiveMode::LineStripAdjacency:
444 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
445 case PrimitiveMode::Triangles:
446 case PrimitiveMode::TriangleFan:
447 case PrimitiveMode::TriangleStrip:
448 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
449 case PrimitiveMode::TrianglesAdjacency:
450 case PrimitiveMode::TriangleStripAdjacency:
451 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800452 default:
453 UNREACHABLE();
454 return false;
455 }
456}
457
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700458// GLES1 texture parameters are a small subset of the others
459bool IsValidGLES1TextureParameter(GLenum pname)
460{
461 switch (pname)
462 {
463 case GL_TEXTURE_MAG_FILTER:
464 case GL_TEXTURE_MIN_FILTER:
465 case GL_TEXTURE_WRAP_S:
466 case GL_TEXTURE_WRAP_T:
467 case GL_TEXTURE_WRAP_R:
468 case GL_GENERATE_MIPMAP:
469 case GL_TEXTURE_CROP_RECT_OES:
470 return true;
471 default:
472 return false;
473 }
474}
Till Rathmannb8543632018-10-02 19:46:14 +0200475
476unsigned int GetSamplerParameterCount(GLenum pname)
477{
478 return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1;
479}
480
Geoff Langf41a7152016-09-19 15:11:17 -0400481} // anonymous namespace
482
Brandon Jonesd1049182018-03-28 10:02:20 -0700483void SetRobustLengthParam(GLsizei *length, GLsizei value)
484{
485 if (length)
486 {
487 *length = value;
488 }
489}
490
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500491bool IsETC2EACFormat(const GLenum format)
492{
493 // ES 3.1, Table 8.19
494 switch (format)
495 {
496 case GL_COMPRESSED_R11_EAC:
497 case GL_COMPRESSED_SIGNED_R11_EAC:
498 case GL_COMPRESSED_RG11_EAC:
499 case GL_COMPRESSED_SIGNED_RG11_EAC:
500 case GL_COMPRESSED_RGB8_ETC2:
501 case GL_COMPRESSED_SRGB8_ETC2:
502 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
503 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
504 case GL_COMPRESSED_RGBA8_ETC2_EAC:
505 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
506 return true;
507
508 default:
509 return false;
510 }
511}
512
Jamie Madill5b772312018-03-08 20:28:32 -0500513bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400514{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800515 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400516 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800517 case TextureType::_2D:
518 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800519 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400520
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800521 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400522 return context->getExtensions().textureRectangle;
523
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800524 case TextureType::_3D:
525 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800526 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500527
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800528 case TextureType::_2DMultisample:
Yizhou Jiang7818a852018-09-06 15:02:04 +0800529 return (context->getClientVersion() >= Version(3, 1) ||
530 context->getExtensions().textureMultisample);
Olli Etuahod310a432018-08-24 15:40:23 +0300531 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300532 return context->getExtensions().textureStorageMultisample2DArray;
Geoff Lang3b573612016-10-31 14:08:10 -0400533
He Yunchaoced53ae2016-11-29 15:00:51 +0800534 default:
535 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500536 }
Jamie Madill35d15012013-10-07 10:46:37 -0400537}
538
Jamie Madill5b772312018-03-08 20:28:32 -0500539bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500540{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800541 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500542 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800543 case TextureType::_2D:
544 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500545 return true;
546
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800547 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400548 return context->getExtensions().textureRectangle;
549
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500550 default:
551 return false;
552 }
553}
554
Jamie Madill5b772312018-03-08 20:28:32 -0500555bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500556{
557 switch (target)
558 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800559 case TextureType::_3D:
560 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300561 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500562
563 default:
564 return false;
565 }
566}
567
Ian Ewellbda75592016-04-18 17:25:54 -0400568// Most texture GL calls are not compatible with external textures, so we have a separate validation
569// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500570bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400571{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800572 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400573 (context->getExtensions().eglImageExternal ||
574 context->getExtensions().eglStreamConsumerExternal);
575}
576
Shannon Woods4dfed832014-03-17 20:03:39 -0400577// This function differs from ValidTextureTarget in that the target must be
578// usable as the destination of a 2D operation-- so a cube face is valid, but
579// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400580// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500581bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400582{
583 switch (target)
584 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800585 case TextureTarget::_2D:
586 case TextureTarget::CubeMapNegativeX:
587 case TextureTarget::CubeMapNegativeY:
588 case TextureTarget::CubeMapNegativeZ:
589 case TextureTarget::CubeMapPositiveX:
590 case TextureTarget::CubeMapPositiveY:
591 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800592 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800593 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400594 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800595 default:
596 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500597 }
598}
599
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800600bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400601 PrimitiveMode transformFeedbackPrimitiveMode,
602 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800603{
604 ASSERT(context);
605
606 if (!context->getExtensions().geometryShader)
607 {
608 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
609 // that does not match the current transform feedback object's draw mode (if transform
610 // feedback is active), (3.0.2, section 2.14, pg 86)
611 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
612 }
613
614 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400615 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800616 {
Jamie Madill493f9572018-05-24 19:52:15 -0400617 case PrimitiveMode::Points:
618 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
619 case PrimitiveMode::Lines:
620 case PrimitiveMode::LineStrip:
621 case PrimitiveMode::LineLoop:
622 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
623 case PrimitiveMode::Triangles:
624 case PrimitiveMode::TriangleFan:
625 case PrimitiveMode::TriangleStrip:
626 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800627 default:
628 UNREACHABLE();
629 return false;
630 }
631}
632
Jamie Madill5b772312018-03-08 20:28:32 -0500633bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400634 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400635 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -0500636 DrawElementsType type,
Jamie Madillbe849e42017-05-02 15:49:00 -0400637 const GLvoid *indices,
638 GLsizei primcount)
639{
640 if (primcount < 0)
641 {
Jamie Madille0472f32018-11-27 16:32:45 -0500642 context->validationError(GL_INVALID_VALUE, kNegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400643 return false;
644 }
645
646 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
647 {
648 return false;
649 }
650
Jamie Madill9fdaa492018-02-16 10:52:11 -0500651 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400652}
653
654bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400655 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400656 GLint first,
657 GLsizei count,
658 GLsizei primcount)
659{
660 if (primcount < 0)
661 {
Jamie Madille0472f32018-11-27 16:32:45 -0500662 context->validationError(GL_INVALID_VALUE, kNegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400663 return false;
664 }
665
666 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
667 {
668 return false;
669 }
670
Jamie Madill9fdaa492018-02-16 10:52:11 -0500671 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400672}
673
Jamie Madill5b772312018-03-08 20:28:32 -0500674bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400675{
676 // Verify there is at least one active attribute with a divisor of zero
677 const State &state = context->getGLState();
678
Jamie Madill785e8a02018-10-04 17:42:00 -0400679 Program *program = state.getLinkedProgram(context);
Jamie Madillbe849e42017-05-02 15:49:00 -0400680
681 const auto &attribs = state.getVertexArray()->getVertexAttributes();
682 const auto &bindings = state.getVertexArray()->getVertexBindings();
683 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
684 {
685 const VertexAttribute &attrib = attribs[attributeIndex];
686 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300687 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400688 {
689 return true;
690 }
691 }
692
Jamie Madille0472f32018-11-27 16:32:45 -0500693 context->validationError(GL_INVALID_OPERATION, kNoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400694 return false;
695}
696
Jamie Madill5b772312018-03-08 20:28:32 -0500697bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500698{
699 switch (target)
700 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800701 case TextureType::_3D:
702 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800703 return true;
704 default:
705 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400706 }
707}
708
Jamie Madill5b772312018-03-08 20:28:32 -0500709bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800710{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800711 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800712 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800713 case TextureType::_2D:
714 case TextureType::_2DArray:
715 case TextureType::_2DMultisample:
716 case TextureType::CubeMap:
717 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800718 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800719 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400720 return context->getExtensions().textureRectangle;
Olli Etuahod310a432018-08-24 15:40:23 +0300721 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300722 return context->getExtensions().textureStorageMultisample2DArray;
He Yunchao11b038b2016-11-22 21:24:04 +0800723 default:
724 return false;
725 }
726}
727
Jamie Madill5b772312018-03-08 20:28:32 -0500728bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500729{
He Yunchaoced53ae2016-11-29 15:00:51 +0800730 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
731 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400732 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500733
734 switch (target)
735 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 case GL_FRAMEBUFFER:
737 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400738
He Yunchaoced53ae2016-11-29 15:00:51 +0800739 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800740 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400741 return (context->getExtensions().framebufferBlit ||
742 context->getClientMajorVersion() >= 3);
743
He Yunchaoced53ae2016-11-29 15:00:51 +0800744 default:
745 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500746 }
747}
748
Jamie Madill5b772312018-03-08 20:28:32 -0500749bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400750{
Jamie Madillc29968b2016-01-20 11:17:23 -0500751 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400752 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800753 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400754 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800755 case TextureType::_2D:
756 case TextureType::_2DArray:
757 case TextureType::_2DMultisample:
Olli Etuahod310a432018-08-24 15:40:23 +0300758 case TextureType::_2DMultisampleArray:
759 // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
760 // level-of-detail" for multisample textures should be. Could maybe make it zero.
Jamie Madillc29968b2016-01-20 11:17:23 -0500761 maxDimension = caps.max2DTextureSize;
762 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800763 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800764 maxDimension = caps.maxCubeMapTextureSize;
765 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800766 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400767 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800768 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800769 maxDimension = caps.max3DTextureSize;
770 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800771 default:
772 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400773 }
774
Jamie Madill43da7c42018-08-01 11:34:49 -0400775 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400776}
777
Jamie Madill5b772312018-03-08 20:28:32 -0500778bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800779 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700780 GLint level,
781 GLsizei width,
782 GLsizei height,
783 GLsizei depth,
784 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400785{
Brandon Jones6cad5662017-06-14 13:25:13 -0700786 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400787 {
Jamie Madille0472f32018-11-27 16:32:45 -0500788 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400789 return false;
790 }
Austin Kinross08528e12015-10-07 16:24:40 -0700791 // TexSubImage parameters can be NPOT without textureNPOT extension,
792 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500793 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500794 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500795 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400796 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400797 {
Jamie Madille0472f32018-11-27 16:32:45 -0500798 context->validationError(GL_INVALID_VALUE, kTextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400799 return false;
800 }
801
802 if (!ValidMipLevel(context, target, level))
803 {
Jamie Madille0472f32018-11-27 16:32:45 -0500804 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400805 return false;
806 }
807
808 return true;
809}
810
Geoff Lang966c9402017-04-18 12:38:27 -0400811bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
812{
813 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
814 (size % blockSize == 0);
815}
816
Jamie Madill5b772312018-03-08 20:28:32 -0500817bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500818 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400819 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500820 GLsizei width,
821 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400822{
Jamie Madill43da7c42018-08-01 11:34:49 -0400823 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400824 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400825 {
826 return false;
827 }
828
Geoff Lang966c9402017-04-18 12:38:27 -0400829 if (width < 0 || height < 0)
830 {
831 return false;
832 }
833
834 if (CompressedTextureFormatRequiresExactSize(internalFormat))
835 {
836 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
837 // block size for level 0 but WebGL disallows this.
838 bool smallerThanBlockSizeAllowed =
839 level > 0 || !context->getExtensions().webglCompatibility;
840
841 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
842 smallerThanBlockSizeAllowed) ||
843 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
844 smallerThanBlockSizeAllowed))
845 {
846 return false;
847 }
848 }
849
850 return true;
851}
852
Jamie Madill5b772312018-03-08 20:28:32 -0500853bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400854 GLenum internalFormat,
855 GLint xoffset,
856 GLint yoffset,
857 GLsizei width,
858 GLsizei height,
859 size_t textureWidth,
860 size_t textureHeight)
861{
Jamie Madill43da7c42018-08-01 11:34:49 -0400862 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400863 if (!formatInfo.compressed)
864 {
865 return false;
866 }
867
Geoff Lang44ff5a72017-02-03 15:15:43 -0500868 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400869 {
870 return false;
871 }
872
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500873 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400874 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500875 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400876 yoffset % formatInfo.compressedBlockHeight != 0)
877 {
878 return false;
879 }
880
881 // Allowed to either have data that is a multiple of block size or is smaller than the block
882 // size but fills the entire mip
883 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
884 static_cast<size_t>(width) == textureWidth &&
885 static_cast<size_t>(height) == textureHeight;
886 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
887 (height % formatInfo.compressedBlockHeight) == 0;
888 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400889 {
890 return false;
891 }
892 }
893
Geoff Langd4f180b2013-09-24 13:57:44 -0400894 return true;
895}
896
Jamie Madill5b772312018-03-08 20:28:32 -0500897bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800898 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400899 GLsizei width,
900 GLsizei height,
901 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400902 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400903 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400904 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400905 GLsizei imageSize)
906{
Jamie Madill43da7c42018-08-01 11:34:49 -0400907 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400908 if (pixelUnpackBuffer == nullptr && imageSize < 0)
909 {
910 // Checks are not required
911 return true;
912 }
913
914 // ...the data would be unpacked from the buffer object such that the memory reads required
915 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400916 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400917 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400918 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400919 const auto &unpack = context->getGLState().getUnpackState();
920
Jamie Madill7f232932018-09-12 11:03:06 -0400921 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
922 GLuint endByte = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400923 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400924 {
Jamie Madille0472f32018-11-27 16:32:45 -0500925 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400926 return false;
927 }
928
Geoff Langff5b2d52016-09-07 11:32:23 -0400929 if (pixelUnpackBuffer)
930 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400931 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400932 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
933 checkedEndByte += checkedOffset;
934
935 if (!checkedEndByte.IsValid() ||
936 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
937 {
938 // Overflow past the end of the buffer
Jamie Madille0472f32018-11-27 16:32:45 -0500939 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400940 return false;
941 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800942 if (context->getExtensions().webglCompatibility &&
943 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
944 {
Jamie Madill610640f2018-11-21 17:28:41 -0500945 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -0500946 kPixelUnpackBufferBoundForTransformFeedback);
James Darpiniane8a93c62018-01-04 18:02:24 -0800947 return false;
948 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400949 }
950 else
951 {
952 ASSERT(imageSize >= 0);
953 if (pixels == nullptr && imageSize != 0)
954 {
Jamie Madillc3e37312018-11-30 15:25:39 -0500955 context->validationError(GL_INVALID_OPERATION, kImageSizeMustBeZero);
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400956 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400957 }
958
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400959 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400960 {
Jamie Madillc3e37312018-11-30 15:25:39 -0500961 context->validationError(GL_INVALID_OPERATION, kImageSizeTooSmall);
Geoff Langff5b2d52016-09-07 11:32:23 -0400962 return false;
963 }
964 }
965
966 return true;
967}
968
Corentin Wallezad3ae902018-03-09 13:40:42 -0500969bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500970{
Geoff Lang37dde692014-01-31 16:34:54 -0500971 switch (queryType)
972 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500973 case QueryType::AnySamples:
974 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400975 return context->getClientMajorVersion() >= 3 ||
976 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500977 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800978 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500979 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800980 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500981 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500983 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800984 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 default:
986 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500987 }
988}
989
Jamie Madill5b772312018-03-08 20:28:32 -0500990bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400991 GLenum type,
992 GLboolean normalized,
993 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400994 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400995 bool pureInteger)
996{
997 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400998 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
999 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1000 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1001 // parameter exceeds 255.
1002 constexpr GLsizei kMaxWebGLStride = 255;
1003 if (stride > kMaxWebGLStride)
1004 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001005 context->validationError(GL_INVALID_VALUE, kStrideExceedsWebGLLimit);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001006 return false;
1007 }
1008
1009 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1010 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1011 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1012 // or an INVALID_OPERATION error is generated.
Frank Henigmand633b152018-10-04 23:34:31 -04001013 angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
1014 size_t typeSize = GetVertexFormatSize(internalType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001015
1016 ASSERT(isPow2(typeSize) && typeSize > 0);
1017 size_t sizeMask = (typeSize - 1);
1018 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1019 {
Jamie Madille0472f32018-11-27 16:32:45 -05001020 context->validationError(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001021 return false;
1022 }
1023
1024 if ((stride & sizeMask) != 0)
1025 {
Jamie Madille0472f32018-11-27 16:32:45 -05001026 context->validationError(GL_INVALID_OPERATION, kStrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001027 return false;
1028 }
1029
1030 return true;
1031}
1032
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001033Program *GetValidProgramNoResolve(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001034{
He Yunchaoced53ae2016-11-29 15:00:51 +08001035 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1036 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1037 // or program object and INVALID_OPERATION if the provided name identifies an object
1038 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001039
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001040 Program *validProgram = context->getProgramNoResolveLink(id);
Dian Xiang769769a2015-09-09 15:20:08 -07001041
1042 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001043 {
Dian Xiang769769a2015-09-09 15:20:08 -07001044 if (context->getShader(id))
1045 {
Jamie Madille0472f32018-11-27 16:32:45 -05001046 context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001047 }
1048 else
1049 {
Jamie Madille0472f32018-11-27 16:32:45 -05001050 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001051 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001052 }
Dian Xiang769769a2015-09-09 15:20:08 -07001053
1054 return validProgram;
1055}
1056
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001057Program *GetValidProgram(Context *context, GLuint id)
1058{
1059 Program *program = GetValidProgramNoResolve(context, id);
1060 if (program)
1061 {
Jamie Madill785e8a02018-10-04 17:42:00 -04001062 program->resolveLink(context);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001063 }
1064 return program;
1065}
1066
Jamie Madill5b772312018-03-08 20:28:32 -05001067Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001068{
1069 // See ValidProgram for spec details.
1070
1071 Shader *validShader = context->getShader(id);
1072
1073 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001074 {
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001075 if (context->getProgramNoResolveLink(id))
Dian Xiang769769a2015-09-09 15:20:08 -07001076 {
Jamie Madille0472f32018-11-27 16:32:45 -05001077 context->validationError(GL_INVALID_OPERATION, kExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001078 }
1079 else
1080 {
Jamie Madille0472f32018-11-27 16:32:45 -05001081 context->validationError(GL_INVALID_VALUE, kInvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001082 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001083 }
Dian Xiang769769a2015-09-09 15:20:08 -07001084
1085 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001086}
1087
Jamie Madill43da7c42018-08-01 11:34:49 -04001088bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001089{
Geoff Langfa125c92017-10-24 13:01:46 -04001090 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001091 {
Geoff Langfa125c92017-10-24 13:01:46 -04001092 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1093 {
Jamie Madille0472f32018-11-27 16:32:45 -05001094 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langfa125c92017-10-24 13:01:46 -04001095 return false;
1096 }
Jamie Madillb4472272014-07-03 10:38:55 -04001097
Geoff Langfa125c92017-10-24 13:01:46 -04001098 // Color attachment 0 is validated below because it is always valid
1099 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001100 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001101 {
Jamie Madille0472f32018-11-27 16:32:45 -05001102 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001103 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001104 }
1105 }
1106 else
1107 {
1108 switch (attachment)
1109 {
Geoff Langfa125c92017-10-24 13:01:46 -04001110 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 case GL_DEPTH_ATTACHMENT:
1112 case GL_STENCIL_ATTACHMENT:
1113 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001114
He Yunchaoced53ae2016-11-29 15:00:51 +08001115 case GL_DEPTH_STENCIL_ATTACHMENT:
1116 if (!context->getExtensions().webglCompatibility &&
1117 context->getClientMajorVersion() < 3)
1118 {
Jamie Madille0472f32018-11-27 16:32:45 -05001119 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
1121 }
1122 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001123
He Yunchaoced53ae2016-11-29 15:00:51 +08001124 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001125 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001126 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001127 }
1128 }
1129
1130 return true;
1131}
1132
Jamie Madill5b772312018-03-08 20:28:32 -05001133bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001134 GLenum target,
1135 GLsizei samples,
1136 GLenum internalformat,
1137 GLsizei width,
1138 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139{
1140 switch (target)
1141 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001142 case GL_RENDERBUFFER:
1143 break;
1144 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001145 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148
1149 if (width < 0 || height < 0 || samples < 0)
1150 {
Jamie Madille0472f32018-11-27 16:32:45 -05001151 context->validationError(GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001152 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001153 }
1154
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001155 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1156 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1157
1158 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001159 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001160 {
Jamie Madille0472f32018-11-27 16:32:45 -05001161 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001162 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001163 }
1164
1165 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1166 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001167 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001168 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001169 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 {
Jamie Madille0472f32018-11-27 16:32:45 -05001171 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
Geoff Langaae65a42014-05-26 12:43:44 -04001175 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 {
Jamie Madille0472f32018-11-27 16:32:45 -05001177 context->validationError(GL_INVALID_VALUE, kResourceMaxRenderbufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04001178 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001179 }
1180
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001181 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 if (handle == 0)
1183 {
Jamie Madille0472f32018-11-27 16:32:45 -05001184 context->validationError(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001185 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001186 }
1187
1188 return true;
1189}
1190
Jamie Madill43da7c42018-08-01 11:34:49 -04001191bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001192 GLenum target,
1193 GLenum attachment,
1194 GLenum renderbuffertarget,
1195 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001196{
Geoff Lange8afa902017-09-27 15:00:43 -04001197 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001198 {
Jamie Madille0472f32018-11-27 16:32:45 -05001199 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001200 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001201 }
1202
Jamie Madill43da7c42018-08-01 11:34:49 -04001203 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001204
Jamie Madill84115c92015-04-23 15:00:07 -04001205 ASSERT(framebuffer);
1206 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207 {
Jamie Madille0472f32018-11-27 16:32:45 -05001208 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001209 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001210 }
1211
Jamie Madillb4472272014-07-03 10:38:55 -04001212 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001213 {
Jamie Madillb4472272014-07-03 10:38:55 -04001214 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001215 }
1216
Jamie Madillab9d82c2014-01-21 16:38:14 -05001217 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1218 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1219 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1220 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1221 if (renderbuffer != 0)
1222 {
1223 if (!context->getRenderbuffer(renderbuffer))
1224 {
Jamie Madille0472f32018-11-27 16:32:45 -05001225 context->validationError(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001226 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001227 }
1228 }
1229
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001230 return true;
1231}
1232
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001233bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001234 GLint srcX0,
1235 GLint srcY0,
1236 GLint srcX1,
1237 GLint srcY1,
1238 GLint dstX0,
1239 GLint dstY0,
1240 GLint dstX1,
1241 GLint dstY1,
1242 GLbitfield mask,
1243 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001244{
1245 switch (filter)
1246 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001247 case GL_NEAREST:
1248 break;
1249 case GL_LINEAR:
1250 break;
1251 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001252 context->validationError(GL_INVALID_ENUM, kBlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 }
1255
1256 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1257 {
Jamie Madille0472f32018-11-27 16:32:45 -05001258 context->validationError(GL_INVALID_VALUE, kBlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001259 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260 }
1261
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1263 // color buffer, leaving only nearest being unfiltered from above
1264 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1265 {
Jamie Madille0472f32018-11-27 16:32:45 -05001266 context->validationError(GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001267 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001268 }
1269
Jamie Madill7f232932018-09-12 11:03:06 -04001270 const auto &glState = context->getGLState();
1271 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1272 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001273
1274 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 {
Jamie Madille0472f32018-11-27 16:32:45 -05001276 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001277 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 }
1279
Jamie Madill427064d2018-04-13 16:20:34 -04001280 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001281 {
Jamie Madill48faf802014-11-06 15:27:22 -05001282 return false;
1283 }
1284
Jamie Madill427064d2018-04-13 16:20:34 -04001285 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001286 {
Jamie Madill48faf802014-11-06 15:27:22 -05001287 return false;
1288 }
1289
Qin Jiajiaaef92162018-02-27 13:51:44 +08001290 if (readFramebuffer->id() == drawFramebuffer->id())
1291 {
Jamie Madille0472f32018-11-27 16:32:45 -05001292 context->validationError(GL_INVALID_OPERATION, kBlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001293 return false;
1294 }
1295
Jamie Madille98b1b52018-03-08 09:47:23 -05001296 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297 {
Geoff Langb1196682014-07-23 13:47:29 -04001298 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 }
1300
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001301 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1302 // always run it in order to avoid triggering driver bugs.
1303 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1304 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001305 {
Jamie Madille0472f32018-11-27 16:32:45 -05001306 context->validationError(GL_INVALID_VALUE, kBlitDimensionsOutOfRange);
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001307 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001308 }
1309
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1311
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 if (mask & GL_COLOR_BUFFER_BIT)
1313 {
Jamie Madill7f232932018-09-12 11:03:06 -04001314 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1315 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001316
He Yunchao66a41a22016-12-15 16:45:05 +08001317 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001318 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001319 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320
Geoff Langa15472a2015-08-11 11:48:03 -04001321 for (size_t drawbufferIdx = 0;
1322 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 {
Geoff Langa15472a2015-08-11 11:48:03 -04001324 const FramebufferAttachment *attachment =
1325 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1326 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001328 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329
Geoff Langb2f3d052013-08-13 12:49:27 -04001330 // The GL ES 3.0.2 spec (pg 193) states that:
1331 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001332 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1333 // as well
1334 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1335 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001336 // Changes with EXT_color_buffer_float:
1337 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001338 GLenum readComponentType = readFormat.info->componentType;
1339 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001340 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001341 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001342 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001343 drawComponentType == GL_SIGNED_NORMALIZED);
1344
1345 if (extensions.colorBufferFloat)
1346 {
1347 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1348 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1349
1350 if (readFixedOrFloat != drawFixedOrFloat)
1351 {
Jamie Madill610640f2018-11-21 17:28:41 -05001352 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001353 kBlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001354 return false;
1355 }
1356 }
1357 else if (readFixedPoint != drawFixedPoint)
1358 {
Jamie Madille0472f32018-11-27 16:32:45 -05001359 context->validationError(GL_INVALID_OPERATION, kBlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001360 return false;
1361 }
1362
1363 if (readComponentType == GL_UNSIGNED_INT &&
1364 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 {
Jamie Madill610640f2018-11-21 17:28:41 -05001366 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001367 kBlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001368 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 }
1370
Jamie Madill6163c752015-12-07 16:32:59 -05001371 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 {
Jamie Madill610640f2018-11-21 17:28:41 -05001373 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001374 kBlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001375 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376 }
1377
Jamie Madilla3944d42016-07-22 22:13:26 -04001378 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001379 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 {
Jamie Madill610640f2018-11-21 17:28:41 -05001381 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001382 kBlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001383 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 }
Geoff Lange4915782017-04-12 15:19:07 -04001385
1386 if (context->getExtensions().webglCompatibility &&
1387 *readColorBuffer == *attachment)
1388 {
Jamie Madille0472f32018-11-27 16:32:45 -05001389 context->validationError(GL_INVALID_OPERATION, kBlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001390 return false;
1391 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 }
1393 }
1394
Jamie Madilla3944d42016-07-22 22:13:26 -04001395 if ((readFormat.info->componentType == GL_INT ||
1396 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1397 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 {
Jamie Madille0472f32018-11-27 16:32:45 -05001399 context->validationError(GL_INVALID_OPERATION, kBlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001400 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 }
He Yunchao66a41a22016-12-15 16:45:05 +08001403 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1404 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1405 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1406 // situation is an application error that would lead to a crash in ANGLE.
1407 else if (drawFramebuffer->hasEnabledDrawBuffer())
1408 {
Jamie Madille0472f32018-11-27 16:32:45 -05001409 context->validationError(GL_INVALID_OPERATION, kBlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001410 return false;
1411 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412 }
1413
He Yunchaoced53ae2016-11-29 15:00:51 +08001414 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001415 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1416 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001418 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001419 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001420 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001421 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001422 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001423 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001425 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 {
Kenneth Russell69382852017-07-21 16:38:44 -04001427 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428 {
Jamie Madill610640f2018-11-21 17:28:41 -05001429 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05001430 kBlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001431 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001434 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 {
Jamie Madille0472f32018-11-27 16:32:45 -05001436 context->validationError(GL_INVALID_OPERATION, kBlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001437 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001438 }
Geoff Lange4915782017-04-12 15:19:07 -04001439
1440 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1441 {
Jamie Madille0472f32018-11-27 16:32:45 -05001442 context->validationError(GL_INVALID_OPERATION, kBlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001443 return false;
1444 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 }
He Yunchao66a41a22016-12-15 16:45:05 +08001446 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1447 else if (drawBuffer)
1448 {
Jamie Madille0472f32018-11-27 16:32:45 -05001449 context->validationError(GL_INVALID_OPERATION, kBlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001450 return false;
1451 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001452 }
1453 }
1454
Martin Radeva3ed4572017-07-27 18:29:37 +03001455 // ANGLE_multiview, Revision 1:
1456 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001457 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1458 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1459 // views in the current read framebuffer is more than one.
1460 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001461 {
Jamie Madille0472f32018-11-27 16:32:45 -05001462 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001463 return false;
1464 }
1465 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1466 {
Jamie Madille0472f32018-11-27 16:32:45 -05001467 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001468 return false;
1469 }
1470
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001471 return true;
1472}
1473
Jamie Madill4928b7c2017-06-20 12:57:39 -04001474bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001475 GLint x,
1476 GLint y,
1477 GLsizei width,
1478 GLsizei height,
1479 GLenum format,
1480 GLenum type,
1481 GLsizei bufSize,
1482 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001483 GLsizei *columns,
1484 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001485 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001486{
1487 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001488 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001489 return false;
1490 }
1491
Brandon Jonesd1049182018-03-28 10:02:20 -07001492 GLsizei writeLength = 0;
1493 GLsizei writeColumns = 0;
1494 GLsizei writeRows = 0;
1495
1496 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1497 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001498 {
Geoff Langb1196682014-07-23 13:47:29 -04001499 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001500 }
1501
Brandon Jonesd1049182018-03-28 10:02:20 -07001502 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001503 {
Geoff Langb1196682014-07-23 13:47:29 -04001504 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001505 }
1506
Brandon Jonesd1049182018-03-28 10:02:20 -07001507 SetRobustLengthParam(length, writeLength);
1508 SetRobustLengthParam(columns, writeColumns);
1509 SetRobustLengthParam(rows, writeRows);
1510
Jamie Madillc29968b2016-01-20 11:17:23 -05001511 return true;
1512}
1513
1514bool ValidateReadnPixelsEXT(Context *context,
1515 GLint x,
1516 GLint y,
1517 GLsizei width,
1518 GLsizei height,
1519 GLenum format,
1520 GLenum type,
1521 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001522 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001523{
1524 if (bufSize < 0)
1525 {
Jamie Madille0472f32018-11-27 16:32:45 -05001526 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001527 return false;
1528 }
1529
Geoff Lang62fce5b2016-09-30 10:46:35 -04001530 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001531 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001532}
Jamie Madill26e91952014-03-05 15:01:27 -05001533
Jamie Madill4928b7c2017-06-20 12:57:39 -04001534bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001535 GLint x,
1536 GLint y,
1537 GLsizei width,
1538 GLsizei height,
1539 GLenum format,
1540 GLenum type,
1541 GLsizei bufSize,
1542 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001543 GLsizei *columns,
1544 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001545 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001546{
Brandon Jonesd1049182018-03-28 10:02:20 -07001547 GLsizei writeLength = 0;
1548 GLsizei writeColumns = 0;
1549 GLsizei writeRows = 0;
1550
Geoff Lang62fce5b2016-09-30 10:46:35 -04001551 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001552 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001553 return false;
1554 }
1555
Brandon Jonesd1049182018-03-28 10:02:20 -07001556 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1557 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001558 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001559 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001560 }
1561
Brandon Jonesd1049182018-03-28 10:02:20 -07001562 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001563 {
1564 return false;
1565 }
1566
Brandon Jonesd1049182018-03-28 10:02:20 -07001567 SetRobustLengthParam(length, writeLength);
1568 SetRobustLengthParam(columns, writeColumns);
1569 SetRobustLengthParam(rows, writeRows);
1570
Geoff Lang62fce5b2016-09-30 10:46:35 -04001571 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001572}
1573
Jamie Madill43da7c42018-08-01 11:34:49 -04001574bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001575{
1576 if (!context->getExtensions().occlusionQueryBoolean &&
1577 !context->getExtensions().disjointTimerQuery)
1578 {
Jamie Madille0472f32018-11-27 16:32:45 -05001579 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001580 return false;
1581 }
1582
Olli Etuaho41997e72016-03-10 13:38:39 +02001583 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001584}
1585
Jamie Madill43da7c42018-08-01 11:34:49 -04001586bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001587{
1588 if (!context->getExtensions().occlusionQueryBoolean &&
1589 !context->getExtensions().disjointTimerQuery)
1590 {
Jamie Madille0472f32018-11-27 16:32:45 -05001591 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001592 return false;
1593 }
1594
Olli Etuaho41997e72016-03-10 13:38:39 +02001595 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001596}
1597
Jamie Madill43da7c42018-08-01 11:34:49 -04001598bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001599{
1600 if (!context->getExtensions().occlusionQueryBoolean &&
1601 !context->getExtensions().disjointTimerQuery)
1602 {
Jamie Madille0472f32018-11-27 16:32:45 -05001603 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Jamie Madillf0e04492017-08-26 15:28:42 -04001604 return false;
1605 }
1606
1607 return true;
1608}
1609
Jamie Madill43da7c42018-08-01 11:34:49 -04001610bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001611{
1612 if (!ValidQueryType(context, target))
1613 {
Jamie Madille0472f32018-11-27 16:32:45 -05001614 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001615 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001616 }
1617
1618 if (id == 0)
1619 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001620 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001621 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001622 }
1623
1624 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1625 // of zero, if the active query object name for <target> is non-zero (for the
1626 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1627 // the active query for either target is non-zero), if <id> is the name of an
1628 // existing query object whose type does not match <target>, or if <id> is the
1629 // active query object name for any query type, the error INVALID_OPERATION is
1630 // generated.
1631
1632 // Ensure no other queries are active
1633 // NOTE: If other queries than occlusion are supported, we will need to check
1634 // separately that:
1635 // a) The query ID passed is not the current active query for any target/type
1636 // b) There are no active queries for the requested target (and in the case
1637 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1638 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001639
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001640 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001641 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001642 context->validationError(GL_INVALID_OPERATION, kOtherQueryActive);
Geoff Langb1196682014-07-23 13:47:29 -04001643 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001644 }
1645
1646 Query *queryObject = context->getQuery(id, true, target);
1647
1648 // check that name was obtained with glGenQueries
1649 if (!queryObject)
1650 {
Jamie Madille0472f32018-11-27 16:32:45 -05001651 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001652 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001653 }
1654
1655 // check for type mismatch
1656 if (queryObject->getType() != target)
1657 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001658 context->validationError(GL_INVALID_OPERATION, kQueryTargetMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001659 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001660 }
1661
1662 return true;
1663}
1664
Jamie Madill43da7c42018-08-01 11:34:49 -04001665bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001666{
1667 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001668 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001669 {
Jamie Madille0472f32018-11-27 16:32:45 -05001670 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671 return false;
1672 }
1673
1674 return ValidateBeginQueryBase(context, target, id);
1675}
1676
Jamie Madill43da7c42018-08-01 11:34:49 -04001677bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001678{
1679 if (!ValidQueryType(context, target))
1680 {
Jamie Madille0472f32018-11-27 16:32:45 -05001681 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001682 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001683 }
1684
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001685 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001686
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001687 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001688 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001689 context->validationError(GL_INVALID_OPERATION, kQueryInactive);
Geoff Langb1196682014-07-23 13:47:29 -04001690 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001691 }
1692
Jamie Madill45c785d2014-05-13 14:09:34 -04001693 return true;
1694}
1695
Jamie Madill43da7c42018-08-01 11:34:49 -04001696bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697{
1698 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001699 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700 {
Jamie Madille0472f32018-11-27 16:32:45 -05001701 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702 return false;
1703 }
1704
1705 return ValidateEndQueryBase(context, target);
1706}
1707
Corentin Wallezad3ae902018-03-09 13:40:42 -05001708bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001709{
1710 if (!context->getExtensions().disjointTimerQuery)
1711 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001712 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713 return false;
1714 }
1715
Corentin Wallezad3ae902018-03-09 13:40:42 -05001716 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001717 {
Jamie Madille0472f32018-11-27 16:32:45 -05001718 context->validationError(GL_INVALID_ENUM, kInvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001719 return false;
1720 }
1721
1722 Query *queryObject = context->getQuery(id, true, target);
1723 if (queryObject == nullptr)
1724 {
Jamie Madille0472f32018-11-27 16:32:45 -05001725 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001726 return false;
1727 }
1728
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001729 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001730 {
Jamie Madille0472f32018-11-27 16:32:45 -05001731 context->validationError(GL_INVALID_OPERATION, kQueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 return false;
1733 }
1734
1735 return true;
1736}
1737
Corentin Wallezad3ae902018-03-09 13:40:42 -05001738bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001739{
Geoff Lang2186c382016-10-14 10:54:54 -04001740 if (numParams)
1741 {
1742 *numParams = 0;
1743 }
1744
Corentin Wallezad3ae902018-03-09 13:40:42 -05001745 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 {
Jamie Madille0472f32018-11-27 16:32:45 -05001747 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748 return false;
1749 }
1750
1751 switch (pname)
1752 {
1753 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001754 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001755 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001756 context->validationError(GL_INVALID_ENUM, kInvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001757 return false;
1758 }
1759 break;
1760 case GL_QUERY_COUNTER_BITS_EXT:
1761 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001762 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001763 {
Jamie Madille0472f32018-11-27 16:32:45 -05001764 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765 return false;
1766 }
1767 break;
1768 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001769 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770 return false;
1771 }
1772
Geoff Lang2186c382016-10-14 10:54:54 -04001773 if (numParams)
1774 {
1775 // All queries return only one value
1776 *numParams = 1;
1777 }
1778
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001779 return true;
1780}
1781
Corentin Wallezad3ae902018-03-09 13:40:42 -05001782bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001783{
1784 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001785 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001786 {
Jamie Madille0472f32018-11-27 16:32:45 -05001787 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 return false;
1789 }
1790
Geoff Lang2186c382016-10-14 10:54:54 -04001791 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001792}
1793
Geoff Lang2186c382016-10-14 10:54:54 -04001794bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001795 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001796 GLenum pname,
1797 GLsizei bufSize,
1798 GLsizei *length,
1799 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001800{
Geoff Lang2186c382016-10-14 10:54:54 -04001801 if (!ValidateRobustEntryPoint(context, bufSize))
1802 {
1803 return false;
1804 }
1805
Brandon Jonesd1049182018-03-28 10:02:20 -07001806 GLsizei numParams = 0;
1807
1808 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001809 {
1810 return false;
1811 }
1812
Brandon Jonesd1049182018-03-28 10:02:20 -07001813 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001814 {
1815 return false;
1816 }
1817
Brandon Jonesd1049182018-03-28 10:02:20 -07001818 SetRobustLengthParam(length, numParams);
1819
Geoff Lang2186c382016-10-14 10:54:54 -04001820 return true;
1821}
1822
1823bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1824{
1825 if (numParams)
1826 {
1827 *numParams = 0;
1828 }
1829
Corentin Wallezad3ae902018-03-09 13:40:42 -05001830 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001831
1832 if (!queryObject)
1833 {
Jamie Madille0472f32018-11-27 16:32:45 -05001834 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001835 return false;
1836 }
1837
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001838 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001839 {
Jamie Madille0472f32018-11-27 16:32:45 -05001840 context->validationError(GL_INVALID_OPERATION, kQueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841 return false;
1842 }
1843
1844 switch (pname)
1845 {
1846 case GL_QUERY_RESULT_EXT:
1847 case GL_QUERY_RESULT_AVAILABLE_EXT:
1848 break;
1849
1850 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001851 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001852 return false;
1853 }
1854
Geoff Lang2186c382016-10-14 10:54:54 -04001855 if (numParams)
1856 {
1857 *numParams = 1;
1858 }
1859
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001860 return true;
1861}
1862
1863bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1864{
1865 if (!context->getExtensions().disjointTimerQuery)
1866 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001867 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001868 return false;
1869 }
Geoff Lang2186c382016-10-14 10:54:54 -04001870 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1871}
1872
1873bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1874 GLuint id,
1875 GLenum pname,
1876 GLsizei bufSize,
1877 GLsizei *length,
1878 GLint *params)
1879{
1880 if (!context->getExtensions().disjointTimerQuery)
1881 {
Jamie Madillc3e37312018-11-30 15:25:39 -05001882 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001883 return false;
1884 }
1885
1886 if (!ValidateRobustEntryPoint(context, bufSize))
1887 {
1888 return false;
1889 }
1890
Brandon Jonesd1049182018-03-28 10:02:20 -07001891 GLsizei numParams = 0;
1892
1893 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001894 {
1895 return false;
1896 }
1897
Brandon Jonesd1049182018-03-28 10:02:20 -07001898 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001899 {
1900 return false;
1901 }
1902
Brandon Jonesd1049182018-03-28 10:02:20 -07001903 SetRobustLengthParam(length, numParams);
1904
Geoff Lang2186c382016-10-14 10:54:54 -04001905 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001906}
1907
1908bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1909{
1910 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001911 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001912 {
Jamie Madille0472f32018-11-27 16:32:45 -05001913 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001914 return false;
1915 }
Geoff Lang2186c382016-10-14 10:54:54 -04001916 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1917}
1918
1919bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1920 GLuint id,
1921 GLenum pname,
1922 GLsizei bufSize,
1923 GLsizei *length,
1924 GLuint *params)
1925{
1926 if (!context->getExtensions().disjointTimerQuery &&
1927 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1928 {
Jamie Madille0472f32018-11-27 16:32:45 -05001929 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001930 return false;
1931 }
1932
1933 if (!ValidateRobustEntryPoint(context, bufSize))
1934 {
1935 return false;
1936 }
1937
Brandon Jonesd1049182018-03-28 10:02:20 -07001938 GLsizei numParams = 0;
1939
1940 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001941 {
1942 return false;
1943 }
1944
Brandon Jonesd1049182018-03-28 10:02:20 -07001945 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001946 {
1947 return false;
1948 }
1949
Brandon Jonesd1049182018-03-28 10:02:20 -07001950 SetRobustLengthParam(length, numParams);
1951
Geoff Lang2186c382016-10-14 10:54:54 -04001952 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001953}
1954
1955bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1956{
1957 if (!context->getExtensions().disjointTimerQuery)
1958 {
Jamie Madille0472f32018-11-27 16:32:45 -05001959 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001960 return false;
1961 }
Geoff Lang2186c382016-10-14 10:54:54 -04001962 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1963}
1964
1965bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1966 GLuint id,
1967 GLenum pname,
1968 GLsizei bufSize,
1969 GLsizei *length,
1970 GLint64 *params)
1971{
1972 if (!context->getExtensions().disjointTimerQuery)
1973 {
Jamie Madille0472f32018-11-27 16:32:45 -05001974 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001975 return false;
1976 }
1977
1978 if (!ValidateRobustEntryPoint(context, bufSize))
1979 {
1980 return false;
1981 }
1982
Brandon Jonesd1049182018-03-28 10:02:20 -07001983 GLsizei numParams = 0;
1984
1985 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001986 {
1987 return false;
1988 }
1989
Brandon Jonesd1049182018-03-28 10:02:20 -07001990 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001991 {
1992 return false;
1993 }
1994
Brandon Jonesd1049182018-03-28 10:02:20 -07001995 SetRobustLengthParam(length, numParams);
1996
Geoff Lang2186c382016-10-14 10:54:54 -04001997 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998}
1999
2000bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2001{
2002 if (!context->getExtensions().disjointTimerQuery)
2003 {
Jamie Madille0472f32018-11-27 16:32:45 -05002004 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002005 return false;
2006 }
Geoff Lang2186c382016-10-14 10:54:54 -04002007 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2008}
2009
2010bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2011 GLuint id,
2012 GLenum pname,
2013 GLsizei bufSize,
2014 GLsizei *length,
2015 GLuint64 *params)
2016{
2017 if (!context->getExtensions().disjointTimerQuery)
2018 {
Jamie Madille0472f32018-11-27 16:32:45 -05002019 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002020 return false;
2021 }
2022
2023 if (!ValidateRobustEntryPoint(context, bufSize))
2024 {
2025 return false;
2026 }
2027
Brandon Jonesd1049182018-03-28 10:02:20 -07002028 GLsizei numParams = 0;
2029
2030 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002031 {
2032 return false;
2033 }
2034
Brandon Jonesd1049182018-03-28 10:02:20 -07002035 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002036 {
2037 return false;
2038 }
2039
Brandon Jonesd1049182018-03-28 10:02:20 -07002040 SetRobustLengthParam(length, numParams);
2041
Geoff Lang2186c382016-10-14 10:54:54 -04002042 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002043}
2044
Jamie Madill5b772312018-03-08 20:28:32 -05002045bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002046 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002047 GLint location,
2048 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002049 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002050{
Jiajia Qin5451d532017-11-16 17:16:34 +08002051 // TODO(Jiajia): Add image uniform check in future.
2052 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002053 {
Jamie Madille0472f32018-11-27 16:32:45 -05002054 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002055 return false;
2056 }
2057
Jiajia Qin5451d532017-11-16 17:16:34 +08002058 if (!program)
2059 {
Jamie Madille0472f32018-11-27 16:32:45 -05002060 context->validationError(GL_INVALID_OPERATION, kInvalidProgramName);
Jiajia Qin5451d532017-11-16 17:16:34 +08002061 return false;
2062 }
2063
2064 if (!program->isLinked())
2065 {
Jamie Madille0472f32018-11-27 16:32:45 -05002066 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiajia Qin5451d532017-11-16 17:16:34 +08002067 return false;
2068 }
2069
2070 if (location == -1)
2071 {
2072 // Silently ignore the uniform command
2073 return false;
2074 }
2075
2076 const auto &uniformLocations = program->getUniformLocations();
2077 size_t castedLocation = static_cast<size_t>(location);
2078 if (castedLocation >= uniformLocations.size())
2079 {
Jamie Madille0472f32018-11-27 16:32:45 -05002080 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
Jiajia Qin5451d532017-11-16 17:16:34 +08002081 return false;
2082 }
2083
2084 const auto &uniformLocation = uniformLocations[castedLocation];
2085 if (uniformLocation.ignored)
2086 {
2087 // Silently ignore the uniform command
2088 return false;
2089 }
2090
2091 if (!uniformLocation.used())
2092 {
Jamie Madille0472f32018-11-27 16:32:45 -05002093 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
Jiajia Qin5451d532017-11-16 17:16:34 +08002094 return false;
2095 }
2096
2097 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2098
2099 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002100 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002101 {
Jamie Madille0472f32018-11-27 16:32:45 -05002102 context->validationError(GL_INVALID_OPERATION, kInvalidUniformCount);
Jiajia Qin5451d532017-11-16 17:16:34 +08002103 return false;
2104 }
2105
2106 *uniformOut = &uniform;
2107 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002108}
2109
Jamie Madill5b772312018-03-08 20:28:32 -05002110bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002111 GLenum uniformType,
2112 GLsizei count,
2113 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002114{
Jiajia Qin5451d532017-11-16 17:16:34 +08002115 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2116 // It is compatible with INT or BOOL.
2117 // Do these cheap tests first, for a little extra speed.
2118 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002119 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002120 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002121 }
2122
Jiajia Qin5451d532017-11-16 17:16:34 +08002123 if (IsSamplerType(uniformType))
2124 {
2125 // Check that the values are in range.
2126 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2127 for (GLsizei i = 0; i < count; ++i)
2128 {
2129 if (value[i] < 0 || value[i] >= max)
2130 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002131 context->validationError(GL_INVALID_VALUE, kSamplerUniformValueOutOfRange);
Jiajia Qin5451d532017-11-16 17:16:34 +08002132 return false;
2133 }
2134 }
2135 return true;
2136 }
2137
Jamie Madillc3e37312018-11-30 15:25:39 -05002138 context->validationError(GL_INVALID_OPERATION, kUniformTypeMismatch);
Jiajia Qin5451d532017-11-16 17:16:34 +08002139 return false;
2140}
2141
Jamie Madill5b772312018-03-08 20:28:32 -05002142bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002143{
2144 // Check that the value type is compatible with uniform type.
2145 if (valueType == uniformType)
2146 {
2147 return true;
2148 }
2149
Jamie Madillc3e37312018-11-30 15:25:39 -05002150 context->validationError(GL_INVALID_OPERATION, kUniformTypeMismatch);
Jiajia Qin5451d532017-11-16 17:16:34 +08002151 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002152}
2153
Jamie Madill5b772312018-03-08 20:28:32 -05002154bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002155{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002156 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002157 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002158 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2159 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002160}
2161
Jamie Madill5b772312018-03-08 20:28:32 -05002162bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002163{
2164 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002165 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmana98a6472017-02-02 21:38:32 -05002166 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2167 ValidateUniform1ivValue(context, uniform->type, count, value);
2168}
2169
Jamie Madill5b772312018-03-08 20:28:32 -05002170bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002171 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002172 GLint location,
2173 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002174 GLboolean transpose)
2175{
Geoff Lang92019432017-11-20 13:09:34 -05002176 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002177 {
Jamie Madille0472f32018-11-27 16:32:45 -05002178 context->validationError(GL_INVALID_VALUE, kES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04002179 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002180 }
2181
Jamie Madill62d31cb2015-09-11 13:25:51 -04002182 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002183 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002184 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2185 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002186}
2187
Jamie Madill5b772312018-03-08 20:28:32 -05002188bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002189{
2190 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2191 {
Jamie Madille0472f32018-11-27 16:32:45 -05002192 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Geoff Langb1196682014-07-23 13:47:29 -04002193 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002194 }
2195
Jamie Madill0af26e12015-03-05 19:54:33 -05002196 const Caps &caps = context->getCaps();
2197
Jamie Madill893ab082014-05-16 16:56:10 -04002198 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2199 {
2200 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2201
Jamie Madill0af26e12015-03-05 19:54:33 -05002202 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002203 {
Jamie Madille0472f32018-11-27 16:32:45 -05002204 context->validationError(GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer);
Geoff Langb1196682014-07-23 13:47:29 -04002205 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002206 }
2207 }
2208
2209 switch (pname)
2210 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002211 case GL_TEXTURE_BINDING_2D:
2212 case GL_TEXTURE_BINDING_CUBE_MAP:
2213 case GL_TEXTURE_BINDING_3D:
2214 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002215 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002216 break;
Olli Etuahod310a432018-08-24 15:40:23 +03002217 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
Olli Etuaho064458a2018-08-30 14:02:02 +03002218 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03002219 {
Jamie Madille0472f32018-11-27 16:32:45 -05002220 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
Olli Etuahod310a432018-08-24 15:40:23 +03002221 return false;
2222 }
2223 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002224 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2225 if (!context->getExtensions().textureRectangle)
2226 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002227 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002228 return false;
2229 }
2230 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002231 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2232 if (!context->getExtensions().eglStreamConsumerExternal &&
2233 !context->getExtensions().eglImageExternal)
2234 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002235 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08002236 return false;
2237 }
2238 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002239
He Yunchaoced53ae2016-11-29 15:00:51 +08002240 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2241 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002242 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002243 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2244 ASSERT(readFramebuffer);
2245
Jamie Madill610640f2018-11-21 17:28:41 -05002246 if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002247 {
Geoff Langb1196682014-07-23 13:47:29 -04002248 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002249 }
2250
Jamie Madille98b1b52018-03-08 09:47:23 -05002251 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002252 {
Jamie Madille0472f32018-11-27 16:32:45 -05002253 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002254 return false;
2255 }
2256
Jamie Madille98b1b52018-03-08 09:47:23 -05002257 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002258 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002259 {
Jamie Madille0472f32018-11-27 16:32:45 -05002260 context->validationError(GL_INVALID_OPERATION, kReadBufferNotAttached);
Geoff Langb1196682014-07-23 13:47:29 -04002261 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002262 }
2263 }
2264 break;
2265
He Yunchaoced53ae2016-11-29 15:00:51 +08002266 default:
2267 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002268 }
2269
2270 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002271 if (*numParams == 0)
2272 {
2273 return false;
2274 }
2275
2276 return true;
2277}
2278
Brandon Jonesd1049182018-03-28 10:02:20 -07002279bool ValidateGetBooleanvRobustANGLE(Context *context,
2280 GLenum pname,
2281 GLsizei bufSize,
2282 GLsizei *length,
2283 GLboolean *params)
2284{
2285 GLenum nativeType;
2286 unsigned int numParams = 0;
2287
2288 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2289 {
2290 return false;
2291 }
2292
2293 SetRobustLengthParam(length, numParams);
2294
2295 return true;
2296}
2297
2298bool ValidateGetFloatvRobustANGLE(Context *context,
2299 GLenum pname,
2300 GLsizei bufSize,
2301 GLsizei *length,
2302 GLfloat *params)
2303{
2304 GLenum nativeType;
2305 unsigned int numParams = 0;
2306
2307 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2308 {
2309 return false;
2310 }
2311
2312 SetRobustLengthParam(length, numParams);
2313
2314 return true;
2315}
2316
2317bool ValidateGetIntegervRobustANGLE(Context *context,
2318 GLenum pname,
2319 GLsizei bufSize,
2320 GLsizei *length,
2321 GLint *data)
2322{
2323 GLenum nativeType;
2324 unsigned int numParams = 0;
2325
2326 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2327 {
2328 return false;
2329 }
2330
2331 SetRobustLengthParam(length, numParams);
2332
2333 return true;
2334}
2335
2336bool ValidateGetInteger64vRobustANGLE(Context *context,
2337 GLenum pname,
2338 GLsizei bufSize,
2339 GLsizei *length,
2340 GLint64 *data)
2341{
2342 GLenum nativeType;
2343 unsigned int numParams = 0;
2344
2345 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2346 {
2347 return false;
2348 }
2349
2350 if (nativeType == GL_INT_64_ANGLEX)
2351 {
2352 CastStateValues(context, nativeType, pname, numParams, data);
2353 return false;
2354 }
2355
2356 SetRobustLengthParam(length, numParams);
2357 return true;
2358}
2359
Jamie Madill5b772312018-03-08 20:28:32 -05002360bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002361 GLenum pname,
2362 GLsizei bufSize,
2363 GLenum *nativeType,
2364 unsigned int *numParams)
2365{
2366 if (!ValidateRobustEntryPoint(context, bufSize))
2367 {
2368 return false;
2369 }
2370
2371 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2372 {
2373 return false;
2374 }
2375
2376 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002377 {
2378 return false;
2379 }
2380
2381 return true;
2382}
2383
Jamie Madill5b772312018-03-08 20:28:32 -05002384bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002385 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002386 GLint level,
2387 GLenum internalformat,
2388 bool isSubImage,
2389 GLint xoffset,
2390 GLint yoffset,
2391 GLint zoffset,
2392 GLint x,
2393 GLint y,
2394 GLsizei width,
2395 GLsizei height,
2396 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002397 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002398{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002399 TextureType texType = TextureTargetToType(target);
2400
Brandon Jones6cad5662017-06-14 13:25:13 -07002401 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002402 {
Jamie Madille0472f32018-11-27 16:32:45 -05002403 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07002404 return false;
2405 }
2406
2407 if (width < 0 || height < 0)
2408 {
Jamie Madille0472f32018-11-27 16:32:45 -05002409 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002410 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002411 }
2412
He Yunchaoced53ae2016-11-29 15:00:51 +08002413 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2414 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002415 {
Jamie Madille0472f32018-11-27 16:32:45 -05002416 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
Geoff Langb1196682014-07-23 13:47:29 -04002417 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002418 }
2419
2420 if (border != 0)
2421 {
Jamie Madille0472f32018-11-27 16:32:45 -05002422 context->validationError(GL_INVALID_VALUE, kInvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002423 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 }
2425
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002426 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002427 {
Jamie Madille0472f32018-11-27 16:32:45 -05002428 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002429 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002430 }
2431
Jamie Madill43da7c42018-08-01 11:34:49 -04002432 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002433 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002434 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002435 {
Geoff Langb1196682014-07-23 13:47:29 -04002436 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002437 }
2438
Jamie Madille98b1b52018-03-08 09:47:23 -05002439 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002440 {
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002442 }
2443
Martin Radev138064f2016-07-15 12:03:41 +03002444 if (readFramebuffer->getReadBufferState() == GL_NONE)
2445 {
Jamie Madille0472f32018-11-27 16:32:45 -05002446 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002447 return false;
2448 }
2449
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002450 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2451 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002452 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002453 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002454 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2455 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002456 {
Jamie Madille0472f32018-11-27 16:32:45 -05002457 context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002458 return false;
2459 }
2460
Martin Radev04e2c3b2017-07-27 16:54:35 +03002461 // ANGLE_multiview spec, Revision 1:
2462 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2463 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002464 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2465 // framebuffer is more than one.
2466 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002467 {
Jamie Madillc3e37312018-11-30 15:25:39 -05002468 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
Martin Radev04e2c3b2017-07-27 16:54:35 +03002469 return false;
2470 }
2471
Jamie Madill43da7c42018-08-01 11:34:49 -04002472 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002473
Geoff Langaae65a42014-05-26 12:43:44 -04002474 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002475 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002476 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002477 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002478 maxDimension = caps.max2DTextureSize;
2479 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002480
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002481 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002482 maxDimension = caps.maxCubeMapTextureSize;
2483 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002484
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002485 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002486 maxDimension = caps.maxRectangleTextureSize;
2487 break;
2488
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002489 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002490 maxDimension = caps.max2DTextureSize;
2491 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002492
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002493 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002494 maxDimension = caps.max3DTextureSize;
2495 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002496
He Yunchaoced53ae2016-11-29 15:00:51 +08002497 default:
Jamie Madille0472f32018-11-27 16:32:45 -05002498 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08002499 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002500 }
2501
Jamie Madill43da7c42018-08-01 11:34:49 -04002502 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002503 if (!texture)
2504 {
Jamie Madille0472f32018-11-27 16:32:45 -05002505 context->validationError(GL_INVALID_OPERATION, kTextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002506 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002507 }
2508
Geoff Lang69cce582015-09-17 13:20:36 -04002509 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002510 {
Jamie Madille0472f32018-11-27 16:32:45 -05002511 context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
Geoff Langb1196682014-07-23 13:47:29 -04002512 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 }
2514
Jamie Madill43da7c42018-08-01 11:34:49 -04002515 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002516 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002517 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002518
Geoff Lang966c9402017-04-18 12:38:27 -04002519 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002520 {
Jamie Madille0472f32018-11-27 16:32:45 -05002521 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
Geoff Langa9be0dc2014-12-17 12:34:40 -05002522 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002523 }
2524
2525 if (isSubImage)
2526 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002527 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2528 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2529 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002530 {
Jamie Madille0472f32018-11-27 16:32:45 -05002531 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
Geoff Langb1196682014-07-23 13:47:29 -04002532 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002533 }
2534 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002535 else
2536 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002537 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002538 {
Jamie Madille0472f32018-11-27 16:32:45 -05002539 context->validationError(GL_INVALID_VALUE, kCubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002540 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002541 }
2542
Geoff Langeb66a6e2016-10-31 13:06:12 -04002543 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002544 {
Jamie Madille0472f32018-11-27 16:32:45 -05002545 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002546 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002547 }
2548
2549 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002550 if (static_cast<int>(width) > maxLevelDimension ||
2551 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002552 {
Jamie Madille0472f32018-11-27 16:32:45 -05002553 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002554 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002555 }
2556 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002557
Jamie Madill0c8abca2016-07-22 20:21:26 -04002558 if (textureFormatOut)
2559 {
2560 *textureFormatOut = texture->getFormat(target, level);
2561 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002562
2563 // Detect texture copying feedback loops for WebGL.
2564 if (context->getExtensions().webglCompatibility)
2565 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002566 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002567 {
Jamie Madille0472f32018-11-27 16:32:45 -05002568 context->validationError(GL_INVALID_OPERATION, kFeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002569 return false;
2570 }
2571 }
2572
Jamie Madill560a8d82014-05-21 13:06:20 -04002573 return true;
2574}
2575
Jamie Madillb42162f2018-08-20 12:58:37 -04002576// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2577// completeness check.
2578const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002579{
2580 const Extensions &extensions = context->getExtensions();
Jamie Madill7f232932018-09-12 11:03:06 -04002581 const State &state = context->getGLState();
Jamie Madille7d80f32018-08-08 15:49:23 -04002582
2583 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2584 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2585 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madilld84b6732018-09-06 15:54:35 -04002586 VertexArray *vertexArray = state.getVertexArray();
2587 ASSERT(vertexArray);
2588
2589 if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
Jamie Madille7d80f32018-08-08 15:49:23 -04002590 {
Jamie Madille0472f32018-11-27 16:32:45 -05002591 return kBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002592 }
2593
2594 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2595 // Section 6.10 of the WebGL 1.0 spec.
2596 Framebuffer *framebuffer = state.getDrawFramebuffer();
Jamie Madilld84b6732018-09-06 15:54:35 -04002597 ASSERT(framebuffer);
2598
Jamie Madille7d80f32018-08-08 15:49:23 -04002599 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2600 {
2601 ASSERT(framebuffer);
2602 const FramebufferAttachment *dsAttachment =
2603 framebuffer->getStencilOrDepthStencilAttachment();
2604 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2605 ASSERT(stencilBits <= 8);
2606
2607 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2608 if (depthStencilState.stencilTest && stencilBits > 0)
2609 {
2610 GLuint maxStencilValue = (1 << stencilBits) - 1;
2611
2612 bool differentRefs =
2613 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2614 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2615 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2616 (depthStencilState.stencilBackWritemask & maxStencilValue);
2617 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2618 (depthStencilState.stencilBackMask & maxStencilValue);
2619
2620 if (differentRefs || differentWritemasks || differentMasks)
2621 {
2622 if (!extensions.webglCompatibility)
2623 {
2624 WARN() << "This ANGLE implementation does not support separate front/back "
2625 "stencil writemasks, reference values, or stencil mask values.";
2626 }
Jamie Madille0472f32018-11-27 16:32:45 -05002627 return kStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002628 }
2629 }
2630 }
2631
2632 if (!framebuffer->isComplete(context))
2633 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002634 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
Jamie Madille0472f32018-11-27 16:32:45 -05002635 return kDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002636 }
2637
2638 if (context->getStateCache().hasAnyEnabledClientAttrib())
2639 {
2640 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2641 {
2642 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2643 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2644 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2645 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madille0472f32018-11-27 16:32:45 -05002646 return kVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002647 }
2648
2649 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2650 {
2651 // This is an application error that would normally result in a crash, but we catch it
2652 // and return an error
Jamie Madille0472f32018-11-27 16:32:45 -05002653 return kVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002654 }
2655 }
2656
2657 // If we are running GLES1, there is no current program.
2658 if (context->getClientVersion() >= Version(2, 0))
2659 {
Jamie Madill785e8a02018-10-04 17:42:00 -04002660 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002661 if (!program)
2662 {
Jamie Madille0472f32018-11-27 16:32:45 -05002663 return kProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002664 }
2665
2666 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2667 // vertex shader stage or fragment shader stage is a undefined behaviour.
2668 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2669 // produce undefined result.
2670 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2671 !program->hasLinkedShaderStage(ShaderType::Fragment))
2672 {
Jamie Madille0472f32018-11-27 16:32:45 -05002673 return kNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002674 }
2675
2676 if (!program->validateSamplers(nullptr, context->getCaps()))
2677 {
Jamie Madille0472f32018-11-27 16:32:45 -05002678 return kTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002679 }
2680
2681 if (extensions.multiview)
2682 {
2683 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2684 const int framebufferNumViews = framebuffer->getNumViews();
2685 if (framebufferNumViews != programNumViews)
2686 {
Jamie Madille0472f32018-11-27 16:32:45 -05002687 return kMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002688 }
2689
2690 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2691 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2692 framebufferNumViews > 1)
2693 {
Jamie Madille0472f32018-11-27 16:32:45 -05002694 return kMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002695 }
2696
2697 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2698 state.isQueryActive(QueryType::TimeElapsed))
2699 {
Jamie Madille0472f32018-11-27 16:32:45 -05002700 return kMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002701 }
2702 }
2703
2704 // Uniform buffer validation
2705 for (unsigned int uniformBlockIndex = 0;
2706 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2707 {
2708 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Jamie Madill7f232932018-09-12 11:03:06 -04002709 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Jamie Madille7d80f32018-08-08 15:49:23 -04002710 const OffsetBindingPointer<Buffer> &uniformBuffer =
2711 state.getIndexedUniformBuffer(blockBinding);
2712
2713 if (uniformBuffer.get() == nullptr)
2714 {
2715 // undefined behaviour
Jamie Madille0472f32018-11-27 16:32:45 -05002716 return kUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002717 }
2718
2719 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2720 if (uniformBufferSize < uniformBlock.dataSize)
2721 {
2722 // undefined behaviour
Jamie Madille0472f32018-11-27 16:32:45 -05002723 return kUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002724 }
2725
2726 if (extensions.webglCompatibility &&
2727 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2728 {
Jamie Madille0472f32018-11-27 16:32:45 -05002729 return kUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002730 }
2731 }
2732
2733 // Do some additonal WebGL-specific validation
2734 if (extensions.webglCompatibility)
2735 {
2736 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2737 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2738 transformFeedbackObject->buffersBoundForOtherUse())
2739 {
Jamie Madille0472f32018-11-27 16:32:45 -05002740 return kTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002741 }
2742
2743 // Detect rendering feedback loops for WebGL.
2744 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2745 {
Jamie Madille0472f32018-11-27 16:32:45 -05002746 return kFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002747 }
2748
2749 // Detect that the vertex shader input types match the attribute types
2750 if (!ValidateVertexShaderAttributeTypeMatch(context))
2751 {
Jamie Madille0472f32018-11-27 16:32:45 -05002752 return kVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002753 }
2754
2755 // Detect that the color buffer types match the fragment shader output types
2756 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2757 {
Jamie Madille0472f32018-11-27 16:32:45 -05002758 return kDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002759 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002760
2761 const VertexArray *vao = context->getGLState().getVertexArray();
2762 if (vao->hasTransformFeedbackBindingConflict(context))
2763 {
Jamie Madille0472f32018-11-27 16:32:45 -05002764 return kVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002765 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002766 }
2767 }
2768
Jamie Madillb42162f2018-08-20 12:58:37 -04002769 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002770}
2771
Jamie Madill16e28fd2018-09-12 11:03:05 -04002772bool ValidateDrawMode(Context *context, PrimitiveMode mode)
Jamie Madill250d33f2014-06-06 17:09:03 -04002773{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002774 const Extensions &extensions = context->getExtensions();
2775
Jamie Madill1aeb1312014-06-20 13:21:25 -04002776 switch (mode)
2777 {
Jamie Madill493f9572018-05-24 19:52:15 -04002778 case PrimitiveMode::Points:
2779 case PrimitiveMode::Lines:
2780 case PrimitiveMode::LineLoop:
2781 case PrimitiveMode::LineStrip:
2782 case PrimitiveMode::Triangles:
2783 case PrimitiveMode::TriangleStrip:
2784 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002785 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002786
Jamie Madill493f9572018-05-24 19:52:15 -04002787 case PrimitiveMode::LinesAdjacency:
2788 case PrimitiveMode::LineStripAdjacency:
2789 case PrimitiveMode::TrianglesAdjacency:
2790 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002791 if (!extensions.geometryShader)
2792 {
Jamie Madille0472f32018-11-27 16:32:45 -05002793 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shaofccebff2018-03-08 13:51:02 +08002794 return false;
2795 }
2796 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002797 default:
Jamie Madille0472f32018-11-27 16:32:45 -05002798 context->validationError(GL_INVALID_ENUM, kInvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002799 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002800 }
2801
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002802 // If we are running GLES1, there is no current program.
2803 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002804 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002805 const State &state = context->getGLState();
2806
Jamie Madill785e8a02018-10-04 17:42:00 -04002807 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002808 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002809
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002810 // Do geometry shader specific validations
2811 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002812 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002813 if (!IsCompatibleDrawModeWithGeometryShader(
2814 mode, program->getGeometryShaderInputPrimitiveType()))
2815 {
Jamie Madill610640f2018-11-21 17:28:41 -05002816 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05002817 kIncompatibleDrawModeAgainstGeometryShader);
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002818 return false;
2819 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002820 }
2821 }
2822
Jamie Madill9fdaa492018-02-16 10:52:11 -05002823 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002824}
2825
Jamie Madill16e28fd2018-09-12 11:03:05 -04002826bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
2827{
2828 if (!context->getStateCache().isValidDrawMode(mode))
2829 {
2830 return ValidateDrawMode(context, mode);
2831 }
2832
2833 if (count < 0)
2834 {
Jamie Madille0472f32018-11-27 16:32:45 -05002835 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Jamie Madill16e28fd2018-09-12 11:03:05 -04002836 return false;
2837 }
2838
2839 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2840 if (drawStatesError)
2841 {
2842 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2843
2844 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2845 // Incomplete.
2846 GLenum errorCode =
Jamie Madille0472f32018-11-27 16:32:45 -05002847 (errorMessage == kDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2848 : GL_INVALID_OPERATION);
Jamie Madill610640f2018-11-21 17:28:41 -05002849 context->validationError(errorCode, errorMessage);
Jamie Madill16e28fd2018-09-12 11:03:05 -04002850 return false;
2851 }
2852
2853 return true;
2854}
2855
Jamie Madill5b772312018-03-08 20:28:32 -05002856bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002857 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002858 GLint first,
2859 GLsizei count,
2860 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002861{
Jamie Madillfd716582014-06-06 17:09:04 -04002862 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002863 {
Jamie Madille0472f32018-11-27 16:32:45 -05002864 context->validationError(GL_INVALID_VALUE, kNegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002865 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002866 }
2867
Jamie Madill16e28fd2018-09-12 11:03:05 -04002868 if (count < 0)
2869 {
Jamie Madille0472f32018-11-27 16:32:45 -05002870 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Jamie Madill16e28fd2018-09-12 11:03:05 -04002871 return false;
2872 }
2873
Jamie Madill7f232932018-09-12 11:03:06 -04002874 const State &state = context->getGLState();
2875 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002876 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002877 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002878 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002879 if (!ValidateTransformFeedbackPrimitiveMode(context,
2880 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002881 {
Jamie Madille0472f32018-11-27 16:32:45 -05002882 context->validationError(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
James Darpinian30b604d2018-03-12 17:26:57 -07002883 return false;
2884 }
2885
2886 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2887 {
Jamie Madille0472f32018-11-27 16:32:45 -05002888 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackBufferTooSmall);
James Darpinian30b604d2018-03-12 17:26:57 -07002889 return false;
2890 }
Jamie Madillfd716582014-06-06 17:09:04 -04002891 }
2892
Jamie Madill16e28fd2018-09-12 11:03:05 -04002893 if (!context->getStateCache().isValidDrawMode(mode))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002894 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002895 return ValidateDrawMode(context, mode);
2896 }
2897
2898 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2899 if (drawStatesError)
2900 {
2901 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2902
2903 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2904 // Incomplete.
2905 GLenum errorCode =
Jamie Madille0472f32018-11-27 16:32:45 -05002906 (errorMessage == kDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2907 : GL_INVALID_OPERATION);
Jamie Madill610640f2018-11-21 17:28:41 -05002908 context->validationError(errorCode, errorMessage);
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002909 return false;
2910 }
2911
Corentin Wallez71168a02016-12-19 15:11:18 -08002912 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002913 // - first < 0 has been checked as an error condition.
2914 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002915 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002916 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002917 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002918 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002919 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2920 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2921 {
Jamie Madille0472f32018-11-27 16:32:45 -05002922 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madill9fdaa492018-02-16 10:52:11 -05002923 return false;
2924 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002925
Jamie Madill2da53562018-08-01 11:34:47 -04002926 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002927 {
2928 return false;
2929 }
Jamie Madillfd716582014-06-06 17:09:04 -04002930 }
2931
2932 return true;
2933}
2934
He Yunchaoced53ae2016-11-29 15:00:51 +08002935bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002936 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002937 GLint first,
2938 GLsizei count,
2939 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002940{
Geoff Lang63c5a592017-09-27 14:08:16 -04002941 if (!context->getExtensions().instancedArrays)
2942 {
Jamie Madille0472f32018-11-27 16:32:45 -05002943 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang63c5a592017-09-27 14:08:16 -04002944 return false;
2945 }
2946
Corentin Wallez170efbf2017-05-02 13:45:01 -04002947 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002948 {
2949 return false;
2950 }
2951
Corentin Wallez0dc97812017-06-22 14:38:44 -04002952 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002953}
2954
Jamie Madill8dc27f92018-11-29 11:45:44 -05002955bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, DrawElementsType type)
Jamie Madillfd716582014-06-06 17:09:04 -04002956{
Jamie Madill8dc27f92018-11-29 11:45:44 -05002957 if (!context->getStateCache().isValidDrawElementsType(type))
Jamie Madill250d33f2014-06-06 17:09:03 -04002958 {
Jamie Madill8dc27f92018-11-29 11:45:44 -05002959 if (type == DrawElementsType::UnsignedInt)
2960 {
Jamie Madille0472f32018-11-27 16:32:45 -05002961 context->validationError(GL_INVALID_ENUM, kTypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002962 return false;
Jamie Madill8dc27f92018-11-29 11:45:44 -05002963 }
2964
2965 ASSERT(type == DrawElementsType::InvalidEnum);
2966 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2967 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002968 }
2969
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002970 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002971
Jamie Madill43da7c42018-08-01 11:34:49 -04002972 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002973 if (curTransformFeedback && curTransformFeedback->isActive() &&
2974 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002975 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002976 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2977 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2978 if (context->getExtensions().geometryShader)
2979 {
2980 if (!ValidateTransformFeedbackPrimitiveMode(
2981 context, curTransformFeedback->getPrimitiveMode(), mode))
2982 {
Jamie Madille0472f32018-11-27 16:32:45 -05002983 context->validationError(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002984 return false;
2985 }
2986 }
2987 else
2988 {
2989 // It is an invalid operation to call DrawElements, DrawRangeElements or
2990 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2991 // 86)
Jamie Madill610640f2018-11-21 17:28:41 -05002992 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05002993 kUnsupportedDrawModeForTransformFeedback);
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002994 return false;
2995 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002996 }
2997
Jiajia Qind9671222016-11-29 16:30:31 +08002998 return true;
2999}
3000
Jamie Madill5b772312018-03-08 20:28:32 -05003001bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003002 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003003 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05003004 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04003005 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003006 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003007{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003008 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003009 return false;
3010
3011 const State &state = context->getGLState();
3012
Corentin Wallez170efbf2017-05-02 13:45:01 -04003013 if (!ValidateDrawBase(context, mode, count))
3014 {
3015 return false;
3016 }
3017
Jamie Madill43da7c42018-08-01 11:34:49 -04003018 const VertexArray *vao = state.getVertexArray();
Jamie Madillcd0a0a32018-10-18 18:41:57 -04003019 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003020
Jamie Madill8dc27f92018-11-29 11:45:44 -05003021 GLuint typeBytes = GetDrawElementsTypeSize(type);
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003022 ASSERT(isPow2(typeBytes) && typeBytes > 0);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003023
3024 if (context->getExtensions().webglCompatibility)
3025 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003026 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3027 {
3028 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3029 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3030 // data type passed to the call, or an INVALID_OPERATION error is generated.
Jamie Madille0472f32018-11-27 16:32:45 -05003031 context->validationError(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003032 return false;
3033 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003034
3035 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3036 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3037 // error is generated.
3038 if (reinterpret_cast<intptr_t>(indices) < 0)
3039 {
Jamie Madille0472f32018-11-27 16:32:45 -05003040 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003041 return false;
3042 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003043
Brandon Jones2a018152018-06-08 15:59:26 -07003044 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003045 {
3046 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003047 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3048 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Jamie Madille0472f32018-11-27 16:32:45 -05003049 context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003050 return false;
3051 }
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003052
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003053 if (elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
James Darpiniane8a93c62018-01-04 18:02:24 -08003054 {
Jamie Madill610640f2018-11-21 17:28:41 -05003055 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05003056 kElementArrayBufferBoundForTransformFeedback);
James Darpiniane8a93c62018-01-04 18:02:24 -08003057 return false;
3058 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003059 }
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003060 else
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003061 {
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003062 if (elementArrayBuffer)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003063 {
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003064 if (elementArrayBuffer->isMapped())
3065 {
3066 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3067 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the
3068 // WebGL 2.0 API. https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madillc3e37312018-11-30 15:25:39 -05003069 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003070 return false;
3071 }
3072 }
3073 else if (!context->getGLState().areClientArraysEnabled())
3074 {
3075 context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003076 return false;
3077 }
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003078 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003079
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003080 if (count > 0)
3081 {
3082 if (!elementArrayBuffer)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003083 {
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003084 if (!indices)
3085 {
3086 // This is an application error that would normally result in a crash, but we catch
3087 // it and return an error
Jamie Madillc3e37312018-11-30 15:25:39 -05003088 context->validationError(GL_INVALID_OPERATION, kElementArrayNoBufferOrPointer);
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003089 return false;
3090 }
3091 }
3092 else
3093 {
3094 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3095 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3096 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3097 constexpr uint64_t kMaxTypeSize = 8;
3098 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3099 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3100 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3101
3102 uint64_t typeSize = typeBytes;
3103 uint64_t elementCount = static_cast<uint64_t>(count);
3104 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3105
3106 // Doing the multiplication here is overflow-safe
3107 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3108
3109 // The offset can be any value, check for overflows
3110 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3111 if (elementDataSizeNoOffset > kUint64Max - offset)
3112 {
3113 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
3114 return false;
3115 }
3116
3117 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3118 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
3119 {
3120 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
3121 return false;
3122 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003123 }
3124
Jamie Madill2c0d6a92018-11-28 14:03:58 -05003125 if (!context->getExtensions().robustBufferAccessBehavior && primcount > 0)
3126 {
3127 // Use the parameter buffer to retrieve and cache the index range.
3128 IndexRange indexRange;
3129 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
3130
3131 // If we use an index greater than our maximum supported index range, return an error.
3132 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
3133 // always return an error if possible here.
3134 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
3135 {
3136 context->validationError(GL_INVALID_OPERATION, kExceedsMaxElement);
3137 return false;
3138 }
3139
3140 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
3141 {
3142 return false;
3143 }
3144
3145 // No op if there are no real indices in the index data (all are primitive restart).
3146 return (indexRange.vertexIndexCount > 0);
3147 }
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003148 }
3149
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003150 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003151}
3152
Jamie Madill5b772312018-03-08 20:28:32 -05003153bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003154 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003155 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05003156 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04003157 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003158 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003159{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003160 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003161}
3162
Geoff Lang3edfe032015-09-04 16:38:24 -04003163bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003164 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003165 GLsizei count,
Jamie Madill8dc27f92018-11-29 11:45:44 -05003166 DrawElementsType type,
Jamie Madill876429b2017-04-20 15:46:24 -04003167 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003168 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003169{
Geoff Lang63c5a592017-09-27 14:08:16 -04003170 if (!context->getExtensions().instancedArrays)
3171 {
Jamie Madille0472f32018-11-27 16:32:45 -05003172 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Lang63c5a592017-09-27 14:08:16 -04003173 return false;
3174 }
3175
Corentin Wallez170efbf2017-05-02 13:45:01 -04003176 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003177 {
3178 return false;
3179 }
3180
Corentin Wallez0dc97812017-06-22 14:38:44 -04003181 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003182}
3183
He Yunchaoced53ae2016-11-29 15:00:51 +08003184bool ValidateFramebufferTextureBase(Context *context,
3185 GLenum target,
3186 GLenum attachment,
3187 GLuint texture,
3188 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003189{
Geoff Lange8afa902017-09-27 15:00:43 -04003190 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003191 {
Jamie Madille0472f32018-11-27 16:32:45 -05003192 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003193 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003194 }
3195
3196 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003197 {
3198 return false;
3199 }
3200
Jamie Madill55ec3b12014-07-03 10:38:57 -04003201 if (texture != 0)
3202 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003203 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003204
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003205 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003206 {
Jamie Madille0472f32018-11-27 16:32:45 -05003207 context->validationError(GL_INVALID_OPERATION, kMissingTexture);
Geoff Langb1196682014-07-23 13:47:29 -04003208 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003209 }
3210
3211 if (level < 0)
3212 {
Jamie Madille0472f32018-11-27 16:32:45 -05003213 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04003214 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003215 }
3216 }
3217
Jamie Madill43da7c42018-08-01 11:34:49 -04003218 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003219 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003220
Jamie Madill84115c92015-04-23 15:00:07 -04003221 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003222 {
Jamie Madille0472f32018-11-27 16:32:45 -05003223 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003224 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003225 }
3226
3227 return true;
3228}
3229
Geoff Langb1196682014-07-23 13:47:29 -04003230bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003231{
3232 if (program == 0)
3233 {
Jamie Madille0472f32018-11-27 16:32:45 -05003234 context->validationError(GL_INVALID_VALUE, kProgramDoesNotExist);
Geoff Langb1196682014-07-23 13:47:29 -04003235 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003236 }
3237
Jamie Madill43da7c42018-08-01 11:34:49 -04003238 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003239 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003240 {
3241 return false;
3242 }
3243
Jamie Madill0063c512014-08-25 15:47:53 -04003244 if (!programObject || !programObject->isLinked())
3245 {
Jamie Madille0472f32018-11-27 16:32:45 -05003246 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003247 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003248 }
3249
Geoff Lang7dd2e102014-11-10 15:19:26 -05003250 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003251 {
Jamie Madille0472f32018-11-27 16:32:45 -05003252 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
Geoff Langb1196682014-07-23 13:47:29 -04003253 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003254 }
3255
Jamie Madill0063c512014-08-25 15:47:53 -04003256 return true;
3257}
3258
Geoff Langf41d0ee2016-10-07 13:04:23 -04003259static bool ValidateSizedGetUniform(Context *context,
3260 GLuint program,
3261 GLint location,
3262 GLsizei bufSize,
3263 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003264{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003265 if (length)
3266 {
3267 *length = 0;
3268 }
3269
Jamie Madill78f41802014-08-25 15:47:55 -04003270 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003271 {
Jamie Madill78f41802014-08-25 15:47:55 -04003272 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003273 }
3274
Geoff Langf41d0ee2016-10-07 13:04:23 -04003275 if (bufSize < 0)
3276 {
Jamie Madille0472f32018-11-27 16:32:45 -05003277 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003278 return false;
3279 }
3280
Jamie Madill44a6fbf2018-10-02 13:38:56 -04003281 Program *programObject = context->getProgramResolveLink(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003282 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003283
Jamie Madill78f41802014-08-25 15:47:55 -04003284 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003285 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003286 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003287 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003288 {
Jamie Madille0472f32018-11-27 16:32:45 -05003289 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003290 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003291 }
3292
Geoff Langf41d0ee2016-10-07 13:04:23 -04003293 if (length)
3294 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003295 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003296 }
3297
Jamie Madill0063c512014-08-25 15:47:53 -04003298 return true;
3299}
3300
He Yunchaoced53ae2016-11-29 15:00:51 +08003301bool ValidateGetnUniformfvEXT(Context *context,
3302 GLuint program,
3303 GLint location,
3304 GLsizei bufSize,
3305 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003306{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003307 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003308}
3309
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003310bool ValidateGetnUniformfvRobustANGLE(Context *context,
3311 GLuint program,
3312 GLint location,
3313 GLsizei bufSize,
3314 GLsizei *length,
3315 GLfloat *params)
3316{
3317 UNIMPLEMENTED();
3318 return false;
3319}
3320
He Yunchaoced53ae2016-11-29 15:00:51 +08003321bool ValidateGetnUniformivEXT(Context *context,
3322 GLuint program,
3323 GLint location,
3324 GLsizei bufSize,
3325 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003326{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003327 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3328}
3329
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003330bool ValidateGetnUniformivRobustANGLE(Context *context,
3331 GLuint program,
3332 GLint location,
3333 GLsizei bufSize,
3334 GLsizei *length,
3335 GLint *params)
3336{
3337 UNIMPLEMENTED();
3338 return false;
3339}
3340
3341bool ValidateGetnUniformuivRobustANGLE(Context *context,
3342 GLuint program,
3343 GLint location,
3344 GLsizei bufSize,
3345 GLsizei *length,
3346 GLuint *params)
3347{
3348 UNIMPLEMENTED();
3349 return false;
3350}
3351
Geoff Langf41d0ee2016-10-07 13:04:23 -04003352bool ValidateGetUniformfvRobustANGLE(Context *context,
3353 GLuint program,
3354 GLint location,
3355 GLsizei bufSize,
3356 GLsizei *length,
3357 GLfloat *params)
3358{
3359 if (!ValidateRobustEntryPoint(context, bufSize))
3360 {
3361 return false;
3362 }
3363
Brandon Jonesd1049182018-03-28 10:02:20 -07003364 GLsizei writeLength = 0;
3365
Geoff Langf41d0ee2016-10-07 13:04:23 -04003366 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003367 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3368 {
3369 return false;
3370 }
3371
3372 SetRobustLengthParam(length, writeLength);
3373
3374 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003375}
3376
3377bool ValidateGetUniformivRobustANGLE(Context *context,
3378 GLuint program,
3379 GLint location,
3380 GLsizei bufSize,
3381 GLsizei *length,
3382 GLint *params)
3383{
3384 if (!ValidateRobustEntryPoint(context, bufSize))
3385 {
3386 return false;
3387 }
3388
Brandon Jonesd1049182018-03-28 10:02:20 -07003389 GLsizei writeLength = 0;
3390
Geoff Langf41d0ee2016-10-07 13:04:23 -04003391 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003392 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3393 {
3394 return false;
3395 }
3396
3397 SetRobustLengthParam(length, writeLength);
3398
3399 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003400}
3401
3402bool ValidateGetUniformuivRobustANGLE(Context *context,
3403 GLuint program,
3404 GLint location,
3405 GLsizei bufSize,
3406 GLsizei *length,
3407 GLuint *params)
3408{
3409 if (!ValidateRobustEntryPoint(context, bufSize))
3410 {
3411 return false;
3412 }
3413
3414 if (context->getClientMajorVersion() < 3)
3415 {
Jamie Madille0472f32018-11-27 16:32:45 -05003416 context->validationError(GL_INVALID_OPERATION, kES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003417 return false;
3418 }
3419
Brandon Jonesd1049182018-03-28 10:02:20 -07003420 GLsizei writeLength = 0;
3421
Geoff Langf41d0ee2016-10-07 13:04:23 -04003422 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003423 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3424 {
3425 return false;
3426 }
3427
3428 SetRobustLengthParam(length, writeLength);
3429
3430 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003431}
3432
He Yunchaoced53ae2016-11-29 15:00:51 +08003433bool ValidateDiscardFramebufferBase(Context *context,
3434 GLenum target,
3435 GLsizei numAttachments,
3436 const GLenum *attachments,
3437 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003438{
3439 if (numAttachments < 0)
3440 {
Jamie Madille0472f32018-11-27 16:32:45 -05003441 context->validationError(GL_INVALID_VALUE, kNegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003442 return false;
3443 }
3444
3445 for (GLsizei i = 0; i < numAttachments; ++i)
3446 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003447 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003448 {
3449 if (defaultFramebuffer)
3450 {
Jamie Madille0472f32018-11-27 16:32:45 -05003451 context->validationError(GL_INVALID_ENUM, kDefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003452 return false;
3453 }
3454
3455 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3456 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003457 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003458 return false;
3459 }
3460 }
3461 else
3462 {
3463 switch (attachments[i])
3464 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003465 case GL_DEPTH_ATTACHMENT:
3466 case GL_STENCIL_ATTACHMENT:
3467 case GL_DEPTH_STENCIL_ATTACHMENT:
3468 if (defaultFramebuffer)
3469 {
Jamie Madill610640f2018-11-21 17:28:41 -05003470 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05003471 kDefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003472 return false;
3473 }
3474 break;
3475 case GL_COLOR:
3476 case GL_DEPTH:
3477 case GL_STENCIL:
3478 if (!defaultFramebuffer)
3479 {
Jamie Madill610640f2018-11-21 17:28:41 -05003480 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05003481 kDefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003482 return false;
3483 }
3484 break;
3485 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003486 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003487 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003488 }
3489 }
3490 }
3491
3492 return true;
3493}
3494
Austin Kinross6ee1e782015-05-29 17:05:37 -07003495bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3496{
Jamie Madill007530e2017-12-28 14:27:04 -05003497 if (!context->getExtensions().debugMarker)
3498 {
3499 // The debug marker calls should not set error state
3500 // However, it seems reasonable to set an error state if the extension is not enabled
Jamie Madille0472f32018-11-27 16:32:45 -05003501 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill007530e2017-12-28 14:27:04 -05003502 return false;
3503 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003504
Jamie Madill007530e2017-12-28 14:27:04 -05003505 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003506 if (length < 0)
3507 {
3508 return false;
3509 }
3510
3511 if (marker == nullptr)
3512 {
3513 return false;
3514 }
3515
3516 return true;
3517}
3518
3519bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3520{
Jamie Madill007530e2017-12-28 14:27:04 -05003521 if (!context->getExtensions().debugMarker)
3522 {
3523 // The debug marker calls should not set error state
3524 // However, it seems reasonable to set an error state if the extension is not enabled
Jamie Madille0472f32018-11-27 16:32:45 -05003525 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill007530e2017-12-28 14:27:04 -05003526 return false;
3527 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003528
Jamie Madill007530e2017-12-28 14:27:04 -05003529 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003530 if (length < 0)
3531 {
3532 return false;
3533 }
3534
3535 if (length > 0 && marker == nullptr)
3536 {
3537 return false;
3538 }
3539
3540 return true;
3541}
3542
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003543bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003544{
Geoff Langa8406172015-07-21 16:53:39 -04003545 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3546 {
Jamie Madille0472f32018-11-27 16:32:45 -05003547 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langa8406172015-07-21 16:53:39 -04003548 return false;
3549 }
3550
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003551 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003552 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003553 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003554 if (!context->getExtensions().eglImage)
3555 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003556 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb66a9092016-05-16 15:59:14 -04003557 }
3558 break;
3559
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003560 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003561 if (!context->getExtensions().eglImageExternal)
3562 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003563 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langb66a9092016-05-16 15:59:14 -04003564 }
Geoff Langa8406172015-07-21 16:53:39 -04003565 break;
3566
3567 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003568 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003569 return false;
3570 }
3571
Rafael Cintron05a449a2018-06-20 18:08:04 -07003572 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003573
Jamie Madill61e16b42017-06-19 11:13:23 -04003574 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003575 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003576 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003577 context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
Geoff Langa8406172015-07-21 16:53:39 -04003578 return false;
3579 }
3580
Jamie Madill007530e2017-12-28 14:27:04 -05003581 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003582 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003583 context->validationError(GL_INVALID_OPERATION, kEGLImageCannotCreate2DMultisampled);
Geoff Langa8406172015-07-21 16:53:39 -04003584 return false;
3585 }
3586
Yuly Novikov2eb54072018-08-22 16:41:26 -04003587 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003588 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003589 context->validationError(GL_INVALID_OPERATION, kEGLImageTextureFormatNotSupported);
Geoff Langa8406172015-07-21 16:53:39 -04003590 return false;
3591 }
3592
Geoff Langdcab33b2015-07-21 13:03:16 -04003593 return true;
3594}
3595
3596bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003597 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003598 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003599{
Geoff Langa8406172015-07-21 16:53:39 -04003600 if (!context->getExtensions().eglImage)
3601 {
Jamie Madille0472f32018-11-27 16:32:45 -05003602 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langa8406172015-07-21 16:53:39 -04003603 return false;
3604 }
3605
3606 switch (target)
3607 {
3608 case GL_RENDERBUFFER:
3609 break;
3610
3611 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003612 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003613 return false;
3614 }
3615
Rafael Cintron05a449a2018-06-20 18:08:04 -07003616 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003617
Jamie Madill61e16b42017-06-19 11:13:23 -04003618 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003619 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003620 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003621 context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
Geoff Langa8406172015-07-21 16:53:39 -04003622 return false;
3623 }
3624
Yuly Novikov2eb54072018-08-22 16:41:26 -04003625 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003626 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003627 context->validationError(GL_INVALID_OPERATION, kEGLImageRenderbufferFormatNotSupported);
Geoff Langa8406172015-07-21 16:53:39 -04003628 return false;
3629 }
3630
Geoff Langdcab33b2015-07-21 13:03:16 -04003631 return true;
3632}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003633
3634bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3635{
Geoff Lang36167ab2015-12-07 10:27:14 -05003636 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003637 {
3638 // The default VAO should always exist
3639 ASSERT(array != 0);
Jamie Madille0472f32018-11-27 16:32:45 -05003640 context->validationError(GL_INVALID_OPERATION, kInvalidVertexArray);
Austin Kinrossbc781f32015-10-26 09:27:38 -07003641 return false;
3642 }
3643
3644 return true;
3645}
3646
Geoff Langc5629752015-12-07 16:29:04 -05003647bool ValidateProgramBinaryBase(Context *context,
3648 GLuint program,
3649 GLenum binaryFormat,
3650 const void *binary,
3651 GLint length)
3652{
3653 Program *programObject = GetValidProgram(context, program);
3654 if (programObject == nullptr)
3655 {
3656 return false;
3657 }
3658
3659 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3660 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3661 programBinaryFormats.end())
3662 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003663 context->validationError(GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
Geoff Langc5629752015-12-07 16:29:04 -05003664 return false;
3665 }
3666
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003667 if (context->hasActiveTransformFeedback(program))
3668 {
3669 // ES 3.0.4 section 2.15 page 91
Jamie Madillc3e37312018-11-30 15:25:39 -05003670 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003671 return false;
3672 }
3673
Geoff Langc5629752015-12-07 16:29:04 -05003674 return true;
3675}
3676
3677bool ValidateGetProgramBinaryBase(Context *context,
3678 GLuint program,
3679 GLsizei bufSize,
3680 GLsizei *length,
3681 GLenum *binaryFormat,
3682 void *binary)
3683{
3684 Program *programObject = GetValidProgram(context, program);
3685 if (programObject == nullptr)
3686 {
3687 return false;
3688 }
3689
3690 if (!programObject->isLinked())
3691 {
Jamie Madille0472f32018-11-27 16:32:45 -05003692 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003693 return false;
3694 }
3695
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003696 if (context->getCaps().programBinaryFormats.empty())
3697 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003698 context->validationError(GL_INVALID_OPERATION, kNoProgramBinaryFormats);
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003699 return false;
3700 }
3701
Geoff Langc5629752015-12-07 16:29:04 -05003702 return true;
3703}
Jamie Madillc29968b2016-01-20 11:17:23 -05003704
Jamie Madill5b772312018-03-08 20:28:32 -05003705bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003706{
3707 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003708 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003709 {
Jamie Madille0472f32018-11-27 16:32:45 -05003710 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Brandon Jonesafa75152017-07-21 13:11:29 -07003711 return false;
3712 }
3713 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3714 {
Jamie Madille0472f32018-11-27 16:32:45 -05003715 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003716 return false;
3717 }
3718
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003719 ASSERT(context->getGLState().getDrawFramebuffer());
3720 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003721 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3722
3723 // This should come first before the check for the default frame buffer
3724 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3725 // rather than INVALID_OPERATION
3726 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3727 {
3728 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3729
3730 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003731 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3732 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003733 {
3734 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003735 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3736 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3737 // 3.1 is still a bit ambiguous about the error, but future specs are
3738 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madillc3e37312018-11-30 15:25:39 -05003739 context->validationError(GL_INVALID_ENUM, kInvalidDrawBuffer);
Olli Etuaho84c9f592016-03-09 14:37:25 +02003740 return false;
3741 }
3742 else if (bufs[colorAttachment] >= maxColorAttachment)
3743 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003744 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
Jamie Madillc29968b2016-01-20 11:17:23 -05003745 return false;
3746 }
3747 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3748 frameBufferId != 0)
3749 {
3750 // INVALID_OPERATION-GL is bound to buffer and ith argument
3751 // is not COLOR_ATTACHMENTi or NONE
Jamie Madillc3e37312018-11-30 15:25:39 -05003752 context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferValue);
Jamie Madillc29968b2016-01-20 11:17:23 -05003753 return false;
3754 }
3755 }
3756
3757 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3758 // and n is not 1 or bufs is bound to value other than BACK and NONE
3759 if (frameBufferId == 0)
3760 {
3761 if (n != 1)
3762 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003763 context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferCountForDefault);
Jamie Madillc29968b2016-01-20 11:17:23 -05003764 return false;
3765 }
3766
3767 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3768 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003769 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferInvalidDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003770 return false;
3771 }
3772 }
3773
3774 return true;
3775}
3776
Geoff Lang496c02d2016-10-20 11:38:11 -07003777bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003778 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003779 GLenum pname,
3780 GLsizei *length,
3781 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003782{
Geoff Lang496c02d2016-10-20 11:38:11 -07003783 if (length)
3784 {
3785 *length = 0;
3786 }
3787
Corentin Walleze4477002017-12-01 14:39:58 -05003788 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003789 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003790 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003791 return false;
3792 }
3793
Geoff Lang496c02d2016-10-20 11:38:11 -07003794 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003795 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003796 case GL_BUFFER_MAP_POINTER:
3797 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003798
Geoff Lang496c02d2016-10-20 11:38:11 -07003799 default:
Jamie Madille0472f32018-11-27 16:32:45 -05003800 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003801 return false;
3802 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003803
3804 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3805 // target bound to zero generate an INVALID_OPERATION error."
3806 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003807 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003808 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003809 context->validationError(GL_INVALID_OPERATION, kBufferPointerNotAvailable);
Olli Etuaho4f667482016-03-30 15:56:35 +03003810 return false;
3811 }
3812
Geoff Lang496c02d2016-10-20 11:38:11 -07003813 if (length)
3814 {
3815 *length = 1;
3816 }
3817
Olli Etuaho4f667482016-03-30 15:56:35 +03003818 return true;
3819}
3820
Corentin Wallez336129f2017-10-17 15:55:40 -04003821bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003822{
Corentin Walleze4477002017-12-01 14:39:58 -05003823 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003824 {
Jamie Madille0472f32018-11-27 16:32:45 -05003825 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003826 return false;
3827 }
3828
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003829 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003830
3831 if (buffer == nullptr || !buffer->isMapped())
3832 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003833 context->validationError(GL_INVALID_OPERATION, kBufferNotMapped);
Olli Etuaho4f667482016-03-30 15:56:35 +03003834 return false;
3835 }
3836
3837 return true;
3838}
3839
3840bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003841 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003842 GLintptr offset,
3843 GLsizeiptr length,
3844 GLbitfield access)
3845{
Corentin Walleze4477002017-12-01 14:39:58 -05003846 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003847 {
Jamie Madille0472f32018-11-27 16:32:45 -05003848 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003849 return false;
3850 }
3851
Brandon Jones6cad5662017-06-14 13:25:13 -07003852 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003853 {
Jamie Madille0472f32018-11-27 16:32:45 -05003854 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07003855 return false;
3856 }
3857
3858 if (length < 0)
3859 {
Jamie Madille0472f32018-11-27 16:32:45 -05003860 context->validationError(GL_INVALID_VALUE, kNegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003861 return false;
3862 }
3863
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003864 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003865
3866 if (!buffer)
3867 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003868 context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
Olli Etuaho4f667482016-03-30 15:56:35 +03003869 return false;
3870 }
3871
3872 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003873 CheckedNumeric<size_t> checkedOffset(offset);
3874 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003875
Jamie Madille2e406c2016-06-02 13:04:10 -04003876 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003877 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003878 context->validationError(GL_INVALID_VALUE, kMapOutOfRange);
Olli Etuaho4f667482016-03-30 15:56:35 +03003879 return false;
3880 }
3881
3882 // Check for invalid bits in the mask
3883 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3884 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3885 GL_MAP_UNSYNCHRONIZED_BIT;
3886
3887 if (access & ~(allAccessBits))
3888 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003889 context->validationError(GL_INVALID_VALUE, kInvalidAccessBits);
Olli Etuaho4f667482016-03-30 15:56:35 +03003890 return false;
3891 }
3892
3893 if (length == 0)
3894 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003895 context->validationError(GL_INVALID_OPERATION, kLengthZero);
Olli Etuaho4f667482016-03-30 15:56:35 +03003896 return false;
3897 }
3898
3899 if (buffer->isMapped())
3900 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003901 context->validationError(GL_INVALID_OPERATION, kBufferAlreadyMapped);
Olli Etuaho4f667482016-03-30 15:56:35 +03003902 return false;
3903 }
3904
3905 // Check for invalid bit combinations
3906 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3907 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003908 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
Olli Etuaho4f667482016-03-30 15:56:35 +03003909 return false;
3910 }
3911
3912 GLbitfield writeOnlyBits =
3913 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3914
3915 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3916 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003917 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsRead);
Olli Etuaho4f667482016-03-30 15:56:35 +03003918 return false;
3919 }
3920
3921 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3922 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003923 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
Olli Etuaho4f667482016-03-30 15:56:35 +03003924 return false;
3925 }
Geoff Lang79f71042017-08-14 16:43:43 -04003926
3927 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003928}
3929
3930bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003931 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003932 GLintptr offset,
3933 GLsizeiptr length)
3934{
Brandon Jones6cad5662017-06-14 13:25:13 -07003935 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003936 {
Jamie Madille0472f32018-11-27 16:32:45 -05003937 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Brandon Jones6cad5662017-06-14 13:25:13 -07003938 return false;
3939 }
3940
3941 if (length < 0)
3942 {
Jamie Madille0472f32018-11-27 16:32:45 -05003943 context->validationError(GL_INVALID_VALUE, kNegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003944 return false;
3945 }
3946
Corentin Walleze4477002017-12-01 14:39:58 -05003947 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003948 {
Jamie Madille0472f32018-11-27 16:32:45 -05003949 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003950 return false;
3951 }
3952
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003953 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003954
3955 if (buffer == nullptr)
3956 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003957 context->validationError(GL_INVALID_OPERATION, kInvalidFlushZero);
Olli Etuaho4f667482016-03-30 15:56:35 +03003958 return false;
3959 }
3960
3961 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3962 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003963 context->validationError(GL_INVALID_OPERATION, kInvalidFlushTarget);
Olli Etuaho4f667482016-03-30 15:56:35 +03003964 return false;
3965 }
3966
3967 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003968 CheckedNumeric<size_t> checkedOffset(offset);
3969 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003970
Jamie Madille2e406c2016-06-02 13:04:10 -04003971 if (!checkedSize.IsValid() ||
3972 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003973 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003974 context->validationError(GL_INVALID_VALUE, kInvalidFlushOutOfRange);
Olli Etuaho4f667482016-03-30 15:56:35 +03003975 return false;
3976 }
3977
3978 return true;
3979}
3980
Olli Etuaho41997e72016-03-10 13:38:39 +02003981bool ValidateGenOrDelete(Context *context, GLint n)
3982{
3983 if (n < 0)
3984 {
Jamie Madille0472f32018-11-27 16:32:45 -05003985 context->validationError(GL_INVALID_VALUE, kNegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003986 return false;
3987 }
3988 return true;
3989}
3990
Jamie Madill5b772312018-03-08 20:28:32 -05003991bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003992{
3993 if (!context->getExtensions().robustClientMemory)
3994 {
Jamie Madillc3e37312018-11-30 15:25:39 -05003995 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Geoff Langff5b2d52016-09-07 11:32:23 -04003996 return false;
3997 }
3998
3999 if (bufSize < 0)
4000 {
Jamie Madille0472f32018-11-27 16:32:45 -05004001 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004002 return false;
4003 }
4004
4005 return true;
4006}
4007
Jamie Madill5b772312018-03-08 20:28:32 -05004008bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004009{
4010 if (bufSize < numParams)
4011 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004012 context->validationError(GL_INVALID_OPERATION, kInsufficientParams);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004013 return false;
4014 }
4015
4016 return true;
4017}
4018
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004019bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004020 GLenum target,
4021 GLenum attachment,
4022 GLenum pname,
4023 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004024{
Geoff Lange8afa902017-09-27 15:00:43 -04004025 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004026 {
Jamie Madille0472f32018-11-27 16:32:45 -05004027 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004028 return false;
4029 }
4030
4031 int clientVersion = context->getClientMajorVersion();
4032
4033 switch (pname)
4034 {
4035 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4036 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4037 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4038 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4039 break;
4040
Martin Radeve5285d22017-07-14 16:23:53 +03004041 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4042 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4043 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4044 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4045 if (clientVersion < 3 || !context->getExtensions().multiview)
4046 {
Jamie Madille0472f32018-11-27 16:32:45 -05004047 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Martin Radeve5285d22017-07-14 16:23:53 +03004048 return false;
4049 }
4050 break;
4051
Geoff Langff5b2d52016-09-07 11:32:23 -04004052 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4053 if (clientVersion < 3 && !context->getExtensions().sRGB)
4054 {
Jamie Madille0472f32018-11-27 16:32:45 -05004055 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004056 return false;
4057 }
4058 break;
4059
4060 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4061 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4062 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4063 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4064 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4065 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4066 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4067 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4068 if (clientVersion < 3)
4069 {
Jamie Madille0472f32018-11-27 16:32:45 -05004070 context->validationError(GL_INVALID_ENUM, kES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004071 return false;
4072 }
4073 break;
4074
Jiawei Shaoa8802472018-05-28 11:17:47 +08004075 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4076 if (!context->getExtensions().geometryShader)
4077 {
Jamie Madille0472f32018-11-27 16:32:45 -05004078 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shaoa8802472018-05-28 11:17:47 +08004079 return false;
4080 }
4081 break;
4082
Geoff Langff5b2d52016-09-07 11:32:23 -04004083 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004084 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Geoff Langff5b2d52016-09-07 11:32:23 -04004085 return false;
4086 }
4087
4088 // Determine if the attachment is a valid enum
4089 switch (attachment)
4090 {
4091 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004092 case GL_DEPTH:
4093 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004094 if (clientVersion < 3)
4095 {
Jamie Madille0472f32018-11-27 16:32:45 -05004096 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 return false;
4098 }
4099 break;
4100
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004101 case GL_DEPTH_STENCIL_ATTACHMENT:
4102 if (clientVersion < 3 && !context->isWebGL1())
4103 {
Jamie Madille0472f32018-11-27 16:32:45 -05004104 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004105 return false;
4106 }
4107 break;
4108
Geoff Langfa125c92017-10-24 13:01:46 -04004109 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004110 case GL_DEPTH_ATTACHMENT:
4111 case GL_STENCIL_ATTACHMENT:
4112 break;
4113
4114 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004115 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4116 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004117 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4118 {
Jamie Madille0472f32018-11-27 16:32:45 -05004119 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004120 return false;
4121 }
4122 break;
4123 }
4124
4125 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4126 ASSERT(framebuffer);
4127
4128 if (framebuffer->id() == 0)
4129 {
4130 if (clientVersion < 3)
4131 {
Jamie Madille0472f32018-11-27 16:32:45 -05004132 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004133 return false;
4134 }
4135
4136 switch (attachment)
4137 {
4138 case GL_BACK:
4139 case GL_DEPTH:
4140 case GL_STENCIL:
4141 break;
4142
4143 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004144 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004145 return false;
4146 }
4147 }
4148 else
4149 {
4150 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4151 {
4152 // Valid attachment query
4153 }
4154 else
4155 {
4156 switch (attachment)
4157 {
4158 case GL_DEPTH_ATTACHMENT:
4159 case GL_STENCIL_ATTACHMENT:
4160 break;
4161
4162 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004163 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004164 {
Jamie Madille0472f32018-11-27 16:32:45 -05004165 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 return false;
4167 }
4168 break;
4169
4170 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004171 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004172 return false;
4173 }
4174 }
4175 }
4176
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004177 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004178 if (attachmentObject)
4179 {
4180 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4181 attachmentObject->type() == GL_TEXTURE ||
4182 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4183
4184 switch (pname)
4185 {
4186 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4187 if (attachmentObject->type() != GL_RENDERBUFFER &&
4188 attachmentObject->type() != GL_TEXTURE)
4189 {
Jamie Madille0472f32018-11-27 16:32:45 -05004190 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004191 return false;
4192 }
4193 break;
4194
4195 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4196 if (attachmentObject->type() != GL_TEXTURE)
4197 {
Jamie Madille0472f32018-11-27 16:32:45 -05004198 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004199 return false;
4200 }
4201 break;
4202
4203 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4204 if (attachmentObject->type() != GL_TEXTURE)
4205 {
Jamie Madille0472f32018-11-27 16:32:45 -05004206 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004207 return false;
4208 }
4209 break;
4210
4211 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4212 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4213 {
Jamie Madille0472f32018-11-27 16:32:45 -05004214 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004215 return false;
4216 }
4217 break;
4218
4219 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4220 if (attachmentObject->type() != GL_TEXTURE)
4221 {
Jamie Madille0472f32018-11-27 16:32:45 -05004222 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004223 return false;
4224 }
4225 break;
4226
4227 default:
4228 break;
4229 }
4230 }
4231 else
4232 {
4233 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4234 // is NONE, then querying any other pname will generate INVALID_ENUM.
4235
4236 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4237 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4238 // INVALID_OPERATION for all other pnames
4239
4240 switch (pname)
4241 {
4242 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4243 break;
4244
4245 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4246 if (clientVersion < 3)
4247 {
Jamie Madill610640f2018-11-21 17:28:41 -05004248 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05004249 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004250 return false;
4251 }
4252 break;
4253
4254 default:
4255 if (clientVersion < 3)
4256 {
Jamie Madill610640f2018-11-21 17:28:41 -05004257 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05004258 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004259 return false;
4260 }
4261 else
4262 {
Jamie Madill610640f2018-11-21 17:28:41 -05004263 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -05004264 kInvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004265 return false;
4266 }
4267 }
4268 }
4269
Martin Radeve5285d22017-07-14 16:23:53 +03004270 if (numParams)
4271 {
4272 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4273 {
4274 // Only when the viewport offsets are queried we can have a varying number of output
4275 // parameters.
4276 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4277 *numParams = numViews * 2;
4278 }
4279 else
4280 {
4281 // For all other queries we can have only one output parameter.
4282 *numParams = 1;
4283 }
4284 }
4285
Geoff Langff5b2d52016-09-07 11:32:23 -04004286 return true;
4287}
4288
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004289bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004290 GLenum target,
4291 GLenum attachment,
4292 GLenum pname,
4293 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004294 GLsizei *length,
4295 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004296{
4297 if (!ValidateRobustEntryPoint(context, bufSize))
4298 {
4299 return false;
4300 }
4301
Brandon Jonesd1049182018-03-28 10:02:20 -07004302 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004303 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004304 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004305 {
4306 return false;
4307 }
4308
Brandon Jonesd1049182018-03-28 10:02:20 -07004309 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004310 {
4311 return false;
4312 }
4313
Brandon Jonesd1049182018-03-28 10:02:20 -07004314 SetRobustLengthParam(length, numParams);
4315
Geoff Langff5b2d52016-09-07 11:32:23 -04004316 return true;
4317}
4318
Jamie Madill5b772312018-03-08 20:28:32 -05004319bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004320 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004321 GLenum pname,
4322 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004323 GLsizei *length,
4324 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004325{
4326 if (!ValidateRobustEntryPoint(context, bufSize))
4327 {
4328 return false;
4329 }
4330
Brandon Jonesd1049182018-03-28 10:02:20 -07004331 GLsizei numParams = 0;
4332
4333 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004334 {
4335 return false;
4336 }
4337
Brandon Jonesd1049182018-03-28 10:02:20 -07004338 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004339 {
4340 return false;
4341 }
4342
Brandon Jonesd1049182018-03-28 10:02:20 -07004343 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004344 return true;
4345}
4346
Jamie Madill5b772312018-03-08 20:28:32 -05004347bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004348 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004349 GLenum pname,
4350 GLsizei bufSize,
4351 GLsizei *length,
4352 GLint64 *params)
4353{
Brandon Jonesd1049182018-03-28 10:02:20 -07004354 GLsizei numParams = 0;
4355
Geoff Langebebe1c2016-10-14 12:01:31 -04004356 if (!ValidateRobustEntryPoint(context, bufSize))
4357 {
4358 return false;
4359 }
4360
Brandon Jonesd1049182018-03-28 10:02:20 -07004361 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004362 {
4363 return false;
4364 }
4365
Brandon Jonesd1049182018-03-28 10:02:20 -07004366 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004367 {
4368 return false;
4369 }
4370
Brandon Jonesd1049182018-03-28 10:02:20 -07004371 SetRobustLengthParam(length, numParams);
4372
Geoff Langff5b2d52016-09-07 11:32:23 -04004373 return true;
4374}
4375
Jamie Madill5b772312018-03-08 20:28:32 -05004376bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004377{
4378 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004379 if (numParams)
4380 {
4381 *numParams = 1;
4382 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004383
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004384 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
4385 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
4386 ? GetValidProgramNoResolve(context, program)
4387 : GetValidProgram(context, program);
Geoff Langff5b2d52016-09-07 11:32:23 -04004388 if (!programObject)
4389 {
4390 return false;
4391 }
4392
4393 switch (pname)
4394 {
4395 case GL_DELETE_STATUS:
4396 case GL_LINK_STATUS:
4397 case GL_VALIDATE_STATUS:
4398 case GL_INFO_LOG_LENGTH:
4399 case GL_ATTACHED_SHADERS:
4400 case GL_ACTIVE_ATTRIBUTES:
4401 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4402 case GL_ACTIVE_UNIFORMS:
4403 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4404 break;
4405
4406 case GL_PROGRAM_BINARY_LENGTH:
4407 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4408 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004409 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004410 return false;
4411 }
4412 break;
4413
4414 case GL_ACTIVE_UNIFORM_BLOCKS:
4415 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4416 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4417 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4418 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4419 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4420 if (context->getClientMajorVersion() < 3)
4421 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004422 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Geoff Langff5b2d52016-09-07 11:32:23 -04004423 return false;
4424 }
4425 break;
4426
Yunchao He61afff12017-03-14 15:34:03 +08004427 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004428 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004429 if (context->getClientVersion() < Version(3, 1))
4430 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004431 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Yunchao He61afff12017-03-14 15:34:03 +08004432 return false;
4433 }
4434 break;
4435
Jiawei Shao6ae51612018-02-23 14:03:25 +08004436 case GL_COMPUTE_WORK_GROUP_SIZE:
4437 if (context->getClientVersion() < Version(3, 1))
4438 {
Jamie Madillc3e37312018-11-30 15:25:39 -05004439 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004440 return false;
4441 }
4442
4443 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4444 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4445 // program which has not been linked successfully, or which does not contain objects to
4446 // form a compute shader.
4447 if (!programObject->isLinked())
4448 {
Jamie Madille0472f32018-11-27 16:32:45 -05004449 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004450 return false;
4451 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004452 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004453 {
Jamie Madille0472f32018-11-27 16:32:45 -05004454 context->validationError(GL_INVALID_OPERATION, kNoActiveComputeShaderStage);
Jiawei Shao6ae51612018-02-23 14:03:25 +08004455 return false;
4456 }
4457 break;
4458
Jiawei Shao447bfac2018-03-14 14:23:40 +08004459 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4460 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4461 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4462 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4463 if (!context->getExtensions().geometryShader)
4464 {
Jamie Madille0472f32018-11-27 16:32:45 -05004465 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004466 return false;
4467 }
4468
4469 // [EXT_geometry_shader] Chapter 7.12
4470 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4471 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4472 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4473 // successfully, or which does not contain objects to form a geometry shader.
4474 if (!programObject->isLinked())
4475 {
Jamie Madille0472f32018-11-27 16:32:45 -05004476 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004477 return false;
4478 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004479 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004480 {
Jamie Madille0472f32018-11-27 16:32:45 -05004481 context->validationError(GL_INVALID_OPERATION, kNoActiveGeometryShaderStage);
Jiawei Shao447bfac2018-03-14 14:23:40 +08004482 return false;
4483 }
4484 break;
4485
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004486 case GL_COMPLETION_STATUS_KHR:
4487 if (!context->getExtensions().parallelShaderCompile)
4488 {
Jamie Madille0472f32018-11-27 16:32:45 -05004489 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004490 return false;
4491 }
4492 break;
4493
Geoff Langff5b2d52016-09-07 11:32:23 -04004494 default:
Jamie Madille0472f32018-11-27 16:32:45 -05004495 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004496 return false;
4497 }
4498
4499 return true;
4500}
4501
4502bool ValidateGetProgramivRobustANGLE(Context *context,
4503 GLuint program,
4504 GLenum pname,
4505 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004506 GLsizei *length,
4507 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004508{
4509 if (!ValidateRobustEntryPoint(context, bufSize))
4510 {
4511 return false;
4512 }
4513
Brandon Jonesd1049182018-03-28 10:02:20 -07004514 GLsizei numParams = 0;
4515
4516 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004517 {
4518 return false;
4519 }
4520
Brandon Jonesd1049182018-03-28 10:02:20 -07004521 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004522 {
4523 return false;
4524 }
4525
Brandon Jonesd1049182018-03-28 10:02:20 -07004526 SetRobustLengthParam(length, numParams);
4527
Geoff Langff5b2d52016-09-07 11:32:23 -04004528 return true;
4529}
4530
Geoff Lang740d9022016-10-07 11:20:52 -04004531bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4532 GLenum target,
4533 GLenum pname,
4534 GLsizei bufSize,
4535 GLsizei *length,
4536 GLint *params)
4537{
4538 if (!ValidateRobustEntryPoint(context, bufSize))
4539 {
4540 return false;
4541 }
4542
Brandon Jonesd1049182018-03-28 10:02:20 -07004543 GLsizei numParams = 0;
4544
4545 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004546 {
4547 return false;
4548 }
4549
Brandon Jonesd1049182018-03-28 10:02:20 -07004550 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004551 {
4552 return false;
4553 }
4554
Brandon Jonesd1049182018-03-28 10:02:20 -07004555 SetRobustLengthParam(length, numParams);
4556
Geoff Lang740d9022016-10-07 11:20:52 -04004557 return true;
4558}
4559
Geoff Langd7d0ed32016-10-07 11:33:51 -04004560bool ValidateGetShaderivRobustANGLE(Context *context,
4561 GLuint shader,
4562 GLenum pname,
4563 GLsizei bufSize,
4564 GLsizei *length,
4565 GLint *params)
4566{
4567 if (!ValidateRobustEntryPoint(context, bufSize))
4568 {
4569 return false;
4570 }
4571
Brandon Jonesd1049182018-03-28 10:02:20 -07004572 GLsizei numParams = 0;
4573
4574 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004575 {
4576 return false;
4577 }
4578
Brandon Jonesd1049182018-03-28 10:02:20 -07004579 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004580 {
4581 return false;
4582 }
4583
Brandon Jonesd1049182018-03-28 10:02:20 -07004584 SetRobustLengthParam(length, numParams);
4585
Geoff Langd7d0ed32016-10-07 11:33:51 -04004586 return true;
4587}
4588
Geoff Langc1984ed2016-10-07 12:41:00 -04004589bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004590 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004591 GLenum pname,
4592 GLsizei bufSize,
4593 GLsizei *length,
4594 GLfloat *params)
4595{
4596 if (!ValidateRobustEntryPoint(context, bufSize))
4597 {
4598 return false;
4599 }
4600
Brandon Jonesd1049182018-03-28 10:02:20 -07004601 GLsizei numParams = 0;
4602
4603 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004604 {
4605 return false;
4606 }
4607
Brandon Jonesd1049182018-03-28 10:02:20 -07004608 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004609 {
4610 return false;
4611 }
4612
Brandon Jonesd1049182018-03-28 10:02:20 -07004613 SetRobustLengthParam(length, numParams);
4614
Geoff Langc1984ed2016-10-07 12:41:00 -04004615 return true;
4616}
4617
Geoff Langc1984ed2016-10-07 12:41:00 -04004618bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004619 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004620 GLenum pname,
4621 GLsizei bufSize,
4622 GLsizei *length,
4623 GLint *params)
4624{
Brandon Jonesd1049182018-03-28 10:02:20 -07004625
Geoff Langc1984ed2016-10-07 12:41:00 -04004626 if (!ValidateRobustEntryPoint(context, bufSize))
4627 {
4628 return false;
4629 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004630 GLsizei numParams = 0;
4631 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004632 {
4633 return false;
4634 }
4635
Brandon Jonesd1049182018-03-28 10:02:20 -07004636 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004637 {
4638 return false;
4639 }
4640
Brandon Jonesd1049182018-03-28 10:02:20 -07004641 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004642 return true;
4643}
4644
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004645bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4646 TextureType target,
4647 GLenum pname,
4648 GLsizei bufSize,
4649 GLsizei *length,
4650 GLint *params)
4651{
4652 UNIMPLEMENTED();
4653 return false;
4654}
4655
4656bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4657 TextureType target,
4658 GLenum pname,
4659 GLsizei bufSize,
4660 GLsizei *length,
4661 GLuint *params)
4662{
4663 UNIMPLEMENTED();
4664 return false;
4665}
4666
Geoff Langc1984ed2016-10-07 12:41:00 -04004667bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004668 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004669 GLenum pname,
4670 GLsizei bufSize,
4671 const GLfloat *params)
4672{
4673 if (!ValidateRobustEntryPoint(context, bufSize))
4674 {
4675 return false;
4676 }
4677
Till Rathmannb8543632018-10-02 19:46:14 +02004678 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004679}
4680
Geoff Langc1984ed2016-10-07 12:41:00 -04004681bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004682 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004683 GLenum pname,
4684 GLsizei bufSize,
4685 const GLint *params)
4686{
4687 if (!ValidateRobustEntryPoint(context, bufSize))
4688 {
4689 return false;
4690 }
4691
Till Rathmannb8543632018-10-02 19:46:14 +02004692 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004693}
4694
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004695bool ValidateTexParameterIivRobustANGLE(Context *context,
4696 TextureType target,
4697 GLenum pname,
4698 GLsizei bufSize,
4699 const GLint *params)
4700{
4701 UNIMPLEMENTED();
4702 return false;
4703}
4704
4705bool ValidateTexParameterIuivRobustANGLE(Context *context,
4706 TextureType target,
4707 GLenum pname,
4708 GLsizei bufSize,
4709 const GLuint *params)
4710{
4711 UNIMPLEMENTED();
4712 return false;
4713}
4714
Geoff Langc1984ed2016-10-07 12:41:00 -04004715bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4716 GLuint sampler,
4717 GLenum pname,
Jamie Madill778bf092018-11-14 09:54:36 -05004718 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004719 GLsizei *length,
4720 GLfloat *params)
4721{
4722 if (!ValidateRobustEntryPoint(context, bufSize))
4723 {
4724 return false;
4725 }
4726
Brandon Jonesd1049182018-03-28 10:02:20 -07004727 GLsizei numParams = 0;
4728
4729 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004730 {
4731 return false;
4732 }
4733
Brandon Jonesd1049182018-03-28 10:02:20 -07004734 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004735 {
4736 return false;
4737 }
4738
Brandon Jonesd1049182018-03-28 10:02:20 -07004739 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004740 return true;
4741}
4742
Geoff Langc1984ed2016-10-07 12:41:00 -04004743bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4744 GLuint sampler,
4745 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004746 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004747 GLsizei *length,
4748 GLint *params)
4749{
4750 if (!ValidateRobustEntryPoint(context, bufSize))
4751 {
4752 return false;
4753 }
4754
Brandon Jonesd1049182018-03-28 10:02:20 -07004755 GLsizei numParams = 0;
4756
4757 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004758 {
4759 return false;
4760 }
4761
Brandon Jonesd1049182018-03-28 10:02:20 -07004762 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004763 {
4764 return false;
4765 }
4766
Brandon Jonesd1049182018-03-28 10:02:20 -07004767 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004768 return true;
4769}
4770
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004771bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4772 GLuint sampler,
4773 GLenum pname,
4774 GLsizei bufSize,
4775 GLsizei *length,
4776 GLint *params)
4777{
4778 UNIMPLEMENTED();
4779 return false;
4780}
4781
4782bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4783 GLuint sampler,
4784 GLenum pname,
4785 GLsizei bufSize,
4786 GLsizei *length,
4787 GLuint *params)
4788{
4789 UNIMPLEMENTED();
4790 return false;
4791}
4792
Geoff Langc1984ed2016-10-07 12:41:00 -04004793bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4794 GLuint sampler,
4795 GLenum pname,
4796 GLsizei bufSize,
4797 const GLfloat *params)
4798{
4799 if (!ValidateRobustEntryPoint(context, bufSize))
4800 {
4801 return false;
4802 }
4803
Till Rathmannb8543632018-10-02 19:46:14 +02004804 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004805}
4806
Geoff Langc1984ed2016-10-07 12:41:00 -04004807bool ValidateSamplerParameterivRobustANGLE(Context *context,
4808 GLuint sampler,
4809 GLenum pname,
4810 GLsizei bufSize,
4811 const GLint *params)
4812{
4813 if (!ValidateRobustEntryPoint(context, bufSize))
4814 {
4815 return false;
4816 }
4817
Till Rathmannb8543632018-10-02 19:46:14 +02004818 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004819}
4820
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004821bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4822 GLuint sampler,
4823 GLenum pname,
4824 GLsizei bufSize,
4825 const GLint *param)
4826{
4827 UNIMPLEMENTED();
4828 return false;
4829}
4830
4831bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4832 GLuint sampler,
4833 GLenum pname,
4834 GLsizei bufSize,
4835 const GLuint *param)
4836{
4837 UNIMPLEMENTED();
4838 return false;
4839}
4840
Geoff Lang0b031062016-10-13 14:30:04 -04004841bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4842 GLuint index,
4843 GLenum pname,
4844 GLsizei bufSize,
4845 GLsizei *length,
4846 GLfloat *params)
4847{
4848 if (!ValidateRobustEntryPoint(context, bufSize))
4849 {
4850 return false;
4851 }
4852
Brandon Jonesd1049182018-03-28 10:02:20 -07004853 GLsizei writeLength = 0;
4854
4855 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004856 {
4857 return false;
4858 }
4859
Brandon Jonesd1049182018-03-28 10:02:20 -07004860 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004861 {
4862 return false;
4863 }
4864
Brandon Jonesd1049182018-03-28 10:02:20 -07004865 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004866 return true;
4867}
4868
Geoff Lang0b031062016-10-13 14:30:04 -04004869bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4870 GLuint index,
4871 GLenum pname,
4872 GLsizei bufSize,
4873 GLsizei *length,
4874 GLint *params)
4875{
4876 if (!ValidateRobustEntryPoint(context, bufSize))
4877 {
4878 return false;
4879 }
4880
Brandon Jonesd1049182018-03-28 10:02:20 -07004881 GLsizei writeLength = 0;
4882
4883 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004884 {
4885 return false;
4886 }
4887
Brandon Jonesd1049182018-03-28 10:02:20 -07004888 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004889 {
4890 return false;
4891 }
4892
Brandon Jonesd1049182018-03-28 10:02:20 -07004893 SetRobustLengthParam(length, writeLength);
4894
Geoff Lang0b031062016-10-13 14:30:04 -04004895 return true;
4896}
4897
Geoff Lang0b031062016-10-13 14:30:04 -04004898bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4899 GLuint index,
4900 GLenum pname,
4901 GLsizei bufSize,
4902 GLsizei *length,
4903 void **pointer)
4904{
4905 if (!ValidateRobustEntryPoint(context, bufSize))
4906 {
4907 return false;
4908 }
4909
Brandon Jonesd1049182018-03-28 10:02:20 -07004910 GLsizei writeLength = 0;
4911
4912 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004913 {
4914 return false;
4915 }
4916
Brandon Jonesd1049182018-03-28 10:02:20 -07004917 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004918 {
4919 return false;
4920 }
4921
Brandon Jonesd1049182018-03-28 10:02:20 -07004922 SetRobustLengthParam(length, writeLength);
4923
Geoff Lang0b031062016-10-13 14:30:04 -04004924 return true;
4925}
4926
Geoff Lang0b031062016-10-13 14:30:04 -04004927bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4928 GLuint index,
4929 GLenum pname,
4930 GLsizei bufSize,
4931 GLsizei *length,
4932 GLint *params)
4933{
4934 if (!ValidateRobustEntryPoint(context, bufSize))
4935 {
4936 return false;
4937 }
4938
Brandon Jonesd1049182018-03-28 10:02:20 -07004939 GLsizei writeLength = 0;
4940
4941 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004942 {
4943 return false;
4944 }
4945
Brandon Jonesd1049182018-03-28 10:02:20 -07004946 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004947 {
4948 return false;
4949 }
4950
Brandon Jonesd1049182018-03-28 10:02:20 -07004951 SetRobustLengthParam(length, writeLength);
4952
Geoff Lang0b031062016-10-13 14:30:04 -04004953 return true;
4954}
4955
Geoff Lang0b031062016-10-13 14:30:04 -04004956bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4957 GLuint index,
4958 GLenum pname,
4959 GLsizei bufSize,
4960 GLsizei *length,
4961 GLuint *params)
4962{
4963 if (!ValidateRobustEntryPoint(context, bufSize))
4964 {
4965 return false;
4966 }
4967
Brandon Jonesd1049182018-03-28 10:02:20 -07004968 GLsizei writeLength = 0;
4969
4970 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004971 {
4972 return false;
4973 }
4974
Brandon Jonesd1049182018-03-28 10:02:20 -07004975 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004976 {
4977 return false;
4978 }
4979
Brandon Jonesd1049182018-03-28 10:02:20 -07004980 SetRobustLengthParam(length, writeLength);
4981
Geoff Lang0b031062016-10-13 14:30:04 -04004982 return true;
4983}
4984
Geoff Lang6899b872016-10-14 11:30:13 -04004985bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4986 GLuint program,
4987 GLuint uniformBlockIndex,
4988 GLenum pname,
4989 GLsizei bufSize,
4990 GLsizei *length,
4991 GLint *params)
4992{
4993 if (!ValidateRobustEntryPoint(context, bufSize))
4994 {
4995 return false;
4996 }
4997
Brandon Jonesd1049182018-03-28 10:02:20 -07004998 GLsizei writeLength = 0;
4999
5000 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5001 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005002 {
5003 return false;
5004 }
5005
Brandon Jonesd1049182018-03-28 10:02:20 -07005006 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005007 {
5008 return false;
5009 }
5010
Brandon Jonesd1049182018-03-28 10:02:20 -07005011 SetRobustLengthParam(length, writeLength);
5012
Geoff Lang6899b872016-10-14 11:30:13 -04005013 return true;
5014}
5015
Brandon Jones416aaf92018-04-10 08:10:16 -07005016bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005017 GLenum target,
5018 GLenum internalformat,
5019 GLenum pname,
5020 GLsizei bufSize,
5021 GLsizei *length,
5022 GLint *params)
5023{
5024 if (!ValidateRobustEntryPoint(context, bufSize))
5025 {
5026 return false;
5027 }
5028
Brandon Jonesd1049182018-03-28 10:02:20 -07005029 GLsizei numParams = 0;
5030
5031 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5032 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005033 {
5034 return false;
5035 }
5036
Brandon Jonesd1049182018-03-28 10:02:20 -07005037 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005038 {
5039 return false;
5040 }
5041
Brandon Jonesd1049182018-03-28 10:02:20 -07005042 SetRobustLengthParam(length, numParams);
5043
Geoff Lang0a9661f2016-10-20 10:59:20 -07005044 return true;
5045}
5046
Jamie Madill5b772312018-03-08 20:28:32 -05005047bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005048 GLuint attribIndex,
5049 GLint size,
5050 GLenum type,
5051 GLboolean pureInteger)
5052{
5053 const Caps &caps = context->getCaps();
5054 if (attribIndex >= caps.maxVertexAttributes)
5055 {
Jamie Madille0472f32018-11-27 16:32:45 -05005056 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005057 return false;
5058 }
5059
5060 if (size < 1 || size > 4)
5061 {
Jamie Madille0472f32018-11-27 16:32:45 -05005062 context->validationError(GL_INVALID_VALUE, kInvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005063 return false;
Shao80957d92017-02-20 21:25:59 +08005064 }
5065
5066 switch (type)
5067 {
5068 case GL_BYTE:
5069 case GL_UNSIGNED_BYTE:
5070 case GL_SHORT:
5071 case GL_UNSIGNED_SHORT:
5072 break;
5073
5074 case GL_INT:
5075 case GL_UNSIGNED_INT:
5076 if (context->getClientMajorVersion() < 3)
5077 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005078 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005079 return false;
5080 }
5081 break;
5082
5083 case GL_FIXED:
5084 case GL_FLOAT:
5085 if (pureInteger)
5086 {
Jamie Madille0472f32018-11-27 16:32:45 -05005087 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005088 return false;
5089 }
5090 break;
5091
5092 case GL_HALF_FLOAT:
5093 if (context->getClientMajorVersion() < 3)
5094 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005095 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005096 return false;
5097 }
5098 if (pureInteger)
5099 {
Jamie Madille0472f32018-11-27 16:32:45 -05005100 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005101 return false;
5102 }
5103 break;
5104
5105 case GL_INT_2_10_10_10_REV:
5106 case GL_UNSIGNED_INT_2_10_10_10_REV:
5107 if (context->getClientMajorVersion() < 3)
5108 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005109 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Shao80957d92017-02-20 21:25:59 +08005110 return false;
5111 }
5112 if (pureInteger)
5113 {
Jamie Madille0472f32018-11-27 16:32:45 -05005114 context->validationError(GL_INVALID_ENUM, kInvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005115 return false;
5116 }
5117 if (size != 4)
5118 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005119 context->validationError(GL_INVALID_OPERATION, kInvalidVertexAttribSize2101010);
Shao80957d92017-02-20 21:25:59 +08005120 return false;
5121 }
5122 break;
5123
5124 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005125 context->validationError(GL_INVALID_ENUM, kInvalidType);
Shao80957d92017-02-20 21:25:59 +08005126 return false;
5127 }
5128
5129 return true;
5130}
5131
Geoff Lang76e65652017-03-27 14:58:02 -04005132// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5133// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5134// specified clear value and the type of a buffer that is being cleared generates an
5135// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005136bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005137 GLint drawbuffer,
5138 const GLenum *validComponentTypes,
5139 size_t validComponentTypeCount)
5140{
5141 const FramebufferAttachment *attachment =
5142 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5143 if (attachment)
5144 {
5145 GLenum componentType = attachment->getFormat().info->componentType;
5146 const GLenum *end = validComponentTypes + validComponentTypeCount;
5147 if (std::find(validComponentTypes, end, componentType) == end)
5148 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005149 context->validationError(GL_INVALID_OPERATION, kNoDefinedClearConversion);
Geoff Lang76e65652017-03-27 14:58:02 -04005150 return false;
5151 }
5152 }
5153
5154 return true;
5155}
5156
Jamie Madill5b772312018-03-08 20:28:32 -05005157bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005158{
5159 if (!ValidateRobustEntryPoint(context, dataSize))
5160 {
5161 return false;
5162 }
5163
Jamie Madill43da7c42018-08-01 11:34:49 -04005164 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005165 if (pixelUnpackBuffer == nullptr)
5166 {
5167 if (dataSize < imageSize)
5168 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005169 context->validationError(GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
Corentin Wallezb2931602017-04-11 15:58:57 -04005170 }
5171 }
5172 return true;
5173}
5174
Jamie Madill5b772312018-03-08 20:28:32 -05005175bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005176 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005177 GLenum pname,
5178 bool pointerVersion,
5179 GLsizei *numParams)
5180{
5181 if (numParams)
5182 {
5183 *numParams = 0;
5184 }
5185
Corentin Walleze4477002017-12-01 14:39:58 -05005186 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005187 {
Jamie Madille0472f32018-11-27 16:32:45 -05005188 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005189 return false;
5190 }
5191
5192 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5193 if (!buffer)
5194 {
5195 // A null buffer means that "0" is bound to the requested buffer target
Jamie Madille0472f32018-11-27 16:32:45 -05005196 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005197 return false;
5198 }
5199
5200 const Extensions &extensions = context->getExtensions();
5201
5202 switch (pname)
5203 {
5204 case GL_BUFFER_USAGE:
5205 case GL_BUFFER_SIZE:
5206 break;
5207
5208 case GL_BUFFER_ACCESS_OES:
5209 if (!extensions.mapBuffer)
5210 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005211 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005212 return false;
5213 }
5214 break;
5215
5216 case GL_BUFFER_MAPPED:
5217 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5218 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5219 !extensions.mapBufferRange)
5220 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005221 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 return false;
5223 }
5224 break;
5225
5226 case GL_BUFFER_MAP_POINTER:
5227 if (!pointerVersion)
5228 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005229 context->validationError(GL_INVALID_ENUM, kInvalidMapPointerQuery);
Jamie Madillbe849e42017-05-02 15:49:00 -04005230 return false;
5231 }
5232 break;
5233
5234 case GL_BUFFER_ACCESS_FLAGS:
5235 case GL_BUFFER_MAP_OFFSET:
5236 case GL_BUFFER_MAP_LENGTH:
5237 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5238 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005239 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005240 return false;
5241 }
5242 break;
5243
Geoff Lang79b91402018-10-04 15:11:30 -04005244 case GL_MEMORY_SIZE_ANGLE:
5245 if (!context->getExtensions().memorySize)
5246 {
Jamie Madille0472f32018-11-27 16:32:45 -05005247 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Geoff Lang79b91402018-10-04 15:11:30 -04005248 return false;
5249 }
5250 break;
5251
Jamie Madillbe849e42017-05-02 15:49:00 -04005252 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005253 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005254 return false;
5255 }
5256
5257 // All buffer parameter queries return one value.
5258 if (numParams)
5259 {
5260 *numParams = 1;
5261 }
5262
5263 return true;
5264}
5265
5266bool ValidateGetRenderbufferParameterivBase(Context *context,
5267 GLenum target,
5268 GLenum pname,
5269 GLsizei *length)
5270{
5271 if (length)
5272 {
5273 *length = 0;
5274 }
5275
5276 if (target != GL_RENDERBUFFER)
5277 {
Jamie Madille0472f32018-11-27 16:32:45 -05005278 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005279 return false;
5280 }
5281
5282 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5283 if (renderbuffer == nullptr)
5284 {
Jamie Madille0472f32018-11-27 16:32:45 -05005285 context->validationError(GL_INVALID_OPERATION, kRenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005286 return false;
5287 }
5288
5289 switch (pname)
5290 {
5291 case GL_RENDERBUFFER_WIDTH:
5292 case GL_RENDERBUFFER_HEIGHT:
5293 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5294 case GL_RENDERBUFFER_RED_SIZE:
5295 case GL_RENDERBUFFER_GREEN_SIZE:
5296 case GL_RENDERBUFFER_BLUE_SIZE:
5297 case GL_RENDERBUFFER_ALPHA_SIZE:
5298 case GL_RENDERBUFFER_DEPTH_SIZE:
5299 case GL_RENDERBUFFER_STENCIL_SIZE:
5300 break;
5301
5302 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5303 if (!context->getExtensions().framebufferMultisample)
5304 {
Jamie Madille0472f32018-11-27 16:32:45 -05005305 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005306 return false;
5307 }
5308 break;
5309
Geoff Lang79b91402018-10-04 15:11:30 -04005310 case GL_MEMORY_SIZE_ANGLE:
5311 if (!context->getExtensions().memorySize)
5312 {
Jamie Madille0472f32018-11-27 16:32:45 -05005313 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Geoff Lang79b91402018-10-04 15:11:30 -04005314 return false;
5315 }
5316 break;
5317
Jamie Madillbe849e42017-05-02 15:49:00 -04005318 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005319 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005320 return false;
5321 }
5322
5323 if (length)
5324 {
5325 *length = 1;
5326 }
5327 return true;
5328}
5329
5330bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5331{
5332 if (length)
5333 {
5334 *length = 0;
5335 }
5336
5337 if (GetValidShader(context, shader) == nullptr)
5338 {
5339 return false;
5340 }
5341
5342 switch (pname)
5343 {
5344 case GL_SHADER_TYPE:
5345 case GL_DELETE_STATUS:
5346 case GL_COMPILE_STATUS:
5347 case GL_INFO_LOG_LENGTH:
5348 case GL_SHADER_SOURCE_LENGTH:
5349 break;
5350
5351 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5352 if (!context->getExtensions().translatedShaderSource)
5353 {
Jamie Madille0472f32018-11-27 16:32:45 -05005354 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005355 return false;
5356 }
5357 break;
5358
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005359 case GL_COMPLETION_STATUS_KHR:
5360 if (!context->getExtensions().parallelShaderCompile)
5361 {
Jamie Madille0472f32018-11-27 16:32:45 -05005362 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005363 return false;
5364 }
5365 break;
5366
Jamie Madillbe849e42017-05-02 15:49:00 -04005367 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005368 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005369 return false;
5370 }
5371
5372 if (length)
5373 {
5374 *length = 1;
5375 }
5376 return true;
5377}
5378
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005379bool ValidateGetTexParameterBase(Context *context,
5380 TextureType target,
5381 GLenum pname,
5382 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005383{
5384 if (length)
5385 {
5386 *length = 0;
5387 }
5388
5389 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5390 {
Jamie Madille0472f32018-11-27 16:32:45 -05005391 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005392 return false;
5393 }
5394
5395 if (context->getTargetTexture(target) == nullptr)
5396 {
5397 // Should only be possible for external textures
Jamie Madille0472f32018-11-27 16:32:45 -05005398 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005399 return false;
5400 }
5401
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005402 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5403 {
Jamie Madille0472f32018-11-27 16:32:45 -05005404 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005405 return false;
5406 }
5407
Jamie Madillbe849e42017-05-02 15:49:00 -04005408 switch (pname)
5409 {
5410 case GL_TEXTURE_MAG_FILTER:
5411 case GL_TEXTURE_MIN_FILTER:
5412 case GL_TEXTURE_WRAP_S:
5413 case GL_TEXTURE_WRAP_T:
5414 break;
5415
5416 case GL_TEXTURE_USAGE_ANGLE:
5417 if (!context->getExtensions().textureUsage)
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
5424 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005425 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005426 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005427 return false;
5428 }
5429 break;
5430
5431 case GL_TEXTURE_IMMUTABLE_FORMAT:
5432 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5433 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005434 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005435 return false;
5436 }
5437 break;
5438
5439 case GL_TEXTURE_WRAP_R:
5440 case GL_TEXTURE_IMMUTABLE_LEVELS:
5441 case GL_TEXTURE_SWIZZLE_R:
5442 case GL_TEXTURE_SWIZZLE_G:
5443 case GL_TEXTURE_SWIZZLE_B:
5444 case GL_TEXTURE_SWIZZLE_A:
5445 case GL_TEXTURE_BASE_LEVEL:
5446 case GL_TEXTURE_MAX_LEVEL:
5447 case GL_TEXTURE_MIN_LOD:
5448 case GL_TEXTURE_MAX_LOD:
5449 case GL_TEXTURE_COMPARE_MODE:
5450 case GL_TEXTURE_COMPARE_FUNC:
5451 if (context->getClientMajorVersion() < 3)
5452 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005453 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
Jamie Madillbe849e42017-05-02 15:49:00 -04005454 return false;
5455 }
5456 break;
5457
5458 case GL_TEXTURE_SRGB_DECODE_EXT:
5459 if (!context->getExtensions().textureSRGBDecode)
5460 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005461 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 return false;
5463 }
5464 break;
5465
Yunchao Hebacaa712018-01-30 14:01:39 +08005466 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5467 if (context->getClientVersion() < Version(3, 1))
5468 {
Jamie Madille0472f32018-11-27 16:32:45 -05005469 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Yunchao Hebacaa712018-01-30 14:01:39 +08005470 return false;
5471 }
5472 break;
5473
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005474 case GL_GENERATE_MIPMAP:
5475 case GL_TEXTURE_CROP_RECT_OES:
5476 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5477 // after GL_OES_draw_texture functionality implemented
5478 if (context->getClientMajorVersion() > 1)
5479 {
Jamie Madille0472f32018-11-27 16:32:45 -05005480 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005481 return false;
5482 }
5483 break;
Geoff Lang79b91402018-10-04 15:11:30 -04005484
5485 case GL_MEMORY_SIZE_ANGLE:
5486 if (!context->getExtensions().memorySize)
5487 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005488 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang79b91402018-10-04 15:11:30 -04005489 return false;
5490 }
5491 break;
5492
Till Rathmannb8543632018-10-02 19:46:14 +02005493 case GL_TEXTURE_BORDER_COLOR:
5494 if (!context->getExtensions().textureBorderClamp)
5495 {
Jamie Madille0472f32018-11-27 16:32:45 -05005496 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02005497 return false;
5498 }
5499 break;
5500
Jamie Madillbe849e42017-05-02 15:49:00 -04005501 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005502 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005503 return false;
5504 }
5505
5506 if (length)
5507 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005508 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005509 }
5510 return true;
5511}
5512
5513bool ValidateGetVertexAttribBase(Context *context,
5514 GLuint index,
5515 GLenum pname,
5516 GLsizei *length,
5517 bool pointer,
5518 bool pureIntegerEntryPoint)
5519{
5520 if (length)
5521 {
5522 *length = 0;
5523 }
5524
5525 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5526 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005527 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005528 return false;
5529 }
5530
5531 if (index >= context->getCaps().maxVertexAttributes)
5532 {
Jamie Madille0472f32018-11-27 16:32:45 -05005533 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005534 return false;
5535 }
5536
5537 if (pointer)
5538 {
5539 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5540 {
Jamie Madille0472f32018-11-27 16:32:45 -05005541 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005542 return false;
5543 }
5544 }
5545 else
5546 {
5547 switch (pname)
5548 {
5549 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5550 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5551 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5552 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5553 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5554 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5555 case GL_CURRENT_VERTEX_ATTRIB:
5556 break;
5557
5558 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5559 static_assert(
5560 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5561 "ANGLE extension enums not equal to GL enums.");
5562 if (context->getClientMajorVersion() < 3 &&
5563 !context->getExtensions().instancedArrays)
5564 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005565 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 return false;
5567 }
5568 break;
5569
5570 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5571 if (context->getClientMajorVersion() < 3)
5572 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005573 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005574 return false;
5575 }
5576 break;
5577
5578 case GL_VERTEX_ATTRIB_BINDING:
5579 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5580 if (context->getClientVersion() < ES_3_1)
5581 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005582 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005583 return false;
5584 }
5585 break;
5586
5587 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005588 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005589 return false;
5590 }
5591 }
5592
5593 if (length)
5594 {
5595 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5596 {
5597 *length = 4;
5598 }
5599 else
5600 {
5601 *length = 1;
5602 }
5603 }
5604
5605 return true;
5606}
5607
Jamie Madill4928b7c2017-06-20 12:57:39 -04005608bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005609 GLint x,
5610 GLint y,
5611 GLsizei width,
5612 GLsizei height,
5613 GLenum format,
5614 GLenum type,
5615 GLsizei bufSize,
5616 GLsizei *length,
5617 GLsizei *columns,
5618 GLsizei *rows,
5619 void *pixels)
5620{
5621 if (length != nullptr)
5622 {
5623 *length = 0;
5624 }
5625 if (rows != nullptr)
5626 {
5627 *rows = 0;
5628 }
5629 if (columns != nullptr)
5630 {
5631 *columns = 0;
5632 }
5633
5634 if (width < 0 || height < 0)
5635 {
Jamie Madille0472f32018-11-27 16:32:45 -05005636 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005637 return false;
5638 }
5639
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005640 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005641
Jamie Madill427064d2018-04-13 16:20:34 -04005642 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005643 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005644 return false;
5645 }
5646
Jamie Madille98b1b52018-03-08 09:47:23 -05005647 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005648 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005649 return false;
5650 }
5651
Jamie Madill690c8eb2018-03-12 15:20:03 -04005652 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005653 ASSERT(framebuffer);
5654
5655 if (framebuffer->getReadBufferState() == GL_NONE)
5656 {
Jamie Madille0472f32018-11-27 16:32:45 -05005657 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005658 return false;
5659 }
5660
5661 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5662 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5663 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5664 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5665 // situation is an application error that would lead to a crash in ANGLE.
5666 if (readBuffer == nullptr)
5667 {
Jamie Madille0472f32018-11-27 16:32:45 -05005668 context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005669 return false;
5670 }
5671
Martin Radev28031682017-07-28 14:47:56 +03005672 // ANGLE_multiview, Revision 1:
5673 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005674 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5675 // in the current read framebuffer is more than one.
5676 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005677 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005678 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
Martin Radev28031682017-07-28 14:47:56 +03005679 return false;
5680 }
5681
Geoff Lang280ba992017-04-18 16:30:58 -04005682 if (context->getExtensions().webglCompatibility)
5683 {
5684 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5685 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5686 // and type before validating the combination of format and type. However, the
5687 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5688 // verifies that GL_INVALID_OPERATION is generated.
5689 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5690 // dEQP/WebGL.
5691 if (!ValidReadPixelsFormatEnum(context, format))
5692 {
Jamie Madille0472f32018-11-27 16:32:45 -05005693 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005694 return false;
5695 }
5696
5697 if (!ValidReadPixelsTypeEnum(context, type))
5698 {
Jamie Madille0472f32018-11-27 16:32:45 -05005699 context->validationError(GL_INVALID_ENUM, kInvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005700 return false;
5701 }
5702 }
5703
Jamie Madill690c8eb2018-03-12 15:20:03 -04005704 GLenum currentFormat = GL_NONE;
5705 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5706
5707 GLenum currentType = GL_NONE;
5708 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5709
Jamie Madillbe849e42017-05-02 15:49:00 -04005710 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5711
5712 bool validFormatTypeCombination =
5713 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5714
5715 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5716 {
Jamie Madille0472f32018-11-27 16:32:45 -05005717 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005718 return false;
5719 }
5720
5721 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005722 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005723 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5724 {
5725 // ...the buffer object's data store is currently mapped.
Jamie Madillc3e37312018-11-30 15:25:39 -05005726 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
Jamie Madillbe849e42017-05-02 15:49:00 -04005727 return false;
5728 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005729 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5730 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5731 {
Jamie Madille0472f32018-11-27 16:32:45 -05005732 context->validationError(GL_INVALID_OPERATION, kPixelPackBufferBoundForTransformFeedback);
James Darpiniane8a93c62018-01-04 18:02:24 -08005733 return false;
5734 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005735
5736 // .. the data would be packed to the buffer object such that the memory writes required
5737 // would exceed the data store size.
5738 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005739 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005740 const auto &pack = context->getGLState().getPackState();
5741
Jamie Madillca2ff382018-07-11 09:01:17 -04005742 GLuint endByte = 0;
5743 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005744 {
Jamie Madille0472f32018-11-27 16:32:45 -05005745 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005746 return false;
5747 }
5748
Jamie Madillbe849e42017-05-02 15:49:00 -04005749 if (bufSize >= 0)
5750 {
5751 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5752 {
Jamie Madille0472f32018-11-27 16:32:45 -05005753 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005754 return false;
5755 }
5756 }
5757
5758 if (pixelPackBuffer != nullptr)
5759 {
5760 CheckedNumeric<size_t> checkedEndByte(endByte);
5761 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5762 checkedEndByte += checkedOffset;
5763
5764 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5765 {
5766 // Overflow past the end of the buffer
Jamie Madille0472f32018-11-27 16:32:45 -05005767 context->validationError(GL_INVALID_OPERATION, kParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005768 return false;
5769 }
5770 }
5771
5772 if (pixelPackBuffer == nullptr && length != nullptr)
5773 {
5774 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5775 {
Jamie Madille0472f32018-11-27 16:32:45 -05005776 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005777 return false;
5778 }
5779
5780 *length = static_cast<GLsizei>(endByte);
5781 }
5782
Geoff Langa953b522018-02-21 16:56:23 -05005783 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 angle::CheckedNumeric<int> clippedExtent(length);
5785 if (start < 0)
5786 {
5787 // "subtract" the area that is less than 0
5788 clippedExtent += start;
5789 }
5790
Geoff Langa953b522018-02-21 16:56:23 -05005791 angle::CheckedNumeric<int> readExtent = start;
5792 readExtent += length;
5793 if (!readExtent.IsValid())
5794 {
5795 return false;
5796 }
5797
5798 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005799 {
5800 // Subtract the region to the right of the read buffer
5801 clippedExtent -= (readExtent - bufferSize);
5802 }
5803
5804 if (!clippedExtent.IsValid())
5805 {
Geoff Langa953b522018-02-21 16:56:23 -05005806 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 }
5808
Geoff Langa953b522018-02-21 16:56:23 -05005809 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5810 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005811 };
5812
Geoff Langa953b522018-02-21 16:56:23 -05005813 GLsizei writtenColumns = 0;
5814 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5815 {
Jamie Madille0472f32018-11-27 16:32:45 -05005816 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langa953b522018-02-21 16:56:23 -05005817 return false;
5818 }
5819
5820 GLsizei writtenRows = 0;
5821 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5822 {
Jamie Madille0472f32018-11-27 16:32:45 -05005823 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
Geoff Langa953b522018-02-21 16:56:23 -05005824 return false;
5825 }
5826
Jamie Madillbe849e42017-05-02 15:49:00 -04005827 if (columns != nullptr)
5828 {
Geoff Langa953b522018-02-21 16:56:23 -05005829 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005830 }
5831
5832 if (rows != nullptr)
5833 {
Geoff Langa953b522018-02-21 16:56:23 -05005834 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005835 }
5836
5837 return true;
5838}
5839
5840template <typename ParamType>
5841bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005842 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005843 GLenum pname,
5844 GLsizei bufSize,
Till Rathmannb8543632018-10-02 19:46:14 +02005845 bool vectorParams,
Jamie Madillbe849e42017-05-02 15:49:00 -04005846 const ParamType *params)
5847{
5848 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5849 {
Jamie Madille0472f32018-11-27 16:32:45 -05005850 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005851 return false;
5852 }
5853
5854 if (context->getTargetTexture(target) == nullptr)
5855 {
5856 // Should only be possible for external textures
Jamie Madille0472f32018-11-27 16:32:45 -05005857 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005858 return false;
5859 }
5860
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005861 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005862 if (bufSize >= 0 && bufSize < minBufSize)
5863 {
Jamie Madille0472f32018-11-27 16:32:45 -05005864 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005865 return false;
5866 }
5867
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005868 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5869 {
Jamie Madille0472f32018-11-27 16:32:45 -05005870 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005871 return false;
5872 }
5873
Jamie Madillbe849e42017-05-02 15:49:00 -04005874 switch (pname)
5875 {
5876 case GL_TEXTURE_WRAP_R:
5877 case GL_TEXTURE_SWIZZLE_R:
5878 case GL_TEXTURE_SWIZZLE_G:
5879 case GL_TEXTURE_SWIZZLE_B:
5880 case GL_TEXTURE_SWIZZLE_A:
5881 case GL_TEXTURE_BASE_LEVEL:
5882 case GL_TEXTURE_MAX_LEVEL:
5883 case GL_TEXTURE_COMPARE_MODE:
5884 case GL_TEXTURE_COMPARE_FUNC:
5885 case GL_TEXTURE_MIN_LOD:
5886 case GL_TEXTURE_MAX_LOD:
5887 if (context->getClientMajorVersion() < 3)
5888 {
Jamie Madille0472f32018-11-27 16:32:45 -05005889 context->validationError(GL_INVALID_ENUM, kES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005890 return false;
5891 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005892 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005893 {
Jamie Madillc3e37312018-11-30 15:25:39 -05005894 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005895 return false;
5896 }
5897 break;
5898
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005899 case GL_GENERATE_MIPMAP:
5900 case GL_TEXTURE_CROP_RECT_OES:
5901 if (context->getClientMajorVersion() > 1)
5902 {
Jamie Madille0472f32018-11-27 16:32:45 -05005903 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005904 return false;
5905 }
5906 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005907 default:
5908 break;
5909 }
5910
Olli Etuahod310a432018-08-24 15:40:23 +03005911 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005912 {
5913 switch (pname)
5914 {
5915 case GL_TEXTURE_MIN_FILTER:
5916 case GL_TEXTURE_MAG_FILTER:
5917 case GL_TEXTURE_WRAP_S:
5918 case GL_TEXTURE_WRAP_T:
5919 case GL_TEXTURE_WRAP_R:
5920 case GL_TEXTURE_MIN_LOD:
5921 case GL_TEXTURE_MAX_LOD:
5922 case GL_TEXTURE_COMPARE_MODE:
5923 case GL_TEXTURE_COMPARE_FUNC:
Till Rathmannb8543632018-10-02 19:46:14 +02005924 case GL_TEXTURE_BORDER_COLOR:
Jamie Madillc3e37312018-11-30 15:25:39 -05005925 context->validationError(GL_INVALID_ENUM, kInvalidPname);
JiangYizhou4cff8d62017-07-06 14:54:09 +08005926 return false;
5927 }
5928 }
5929
Jamie Madillbe849e42017-05-02 15:49:00 -04005930 switch (pname)
5931 {
5932 case GL_TEXTURE_WRAP_S:
5933 case GL_TEXTURE_WRAP_T:
5934 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005935 {
5936 bool restrictedWrapModes =
5937 target == TextureType::External || target == TextureType::Rectangle;
5938 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005939 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005940 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005941 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005942 }
5943 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005944
5945 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005946 {
5947 bool restrictedMinFilter =
5948 target == TextureType::External || target == TextureType::Rectangle;
5949 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005950 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005951 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005952 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005953 }
5954 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005955
5956 case GL_TEXTURE_MAG_FILTER:
5957 if (!ValidateTextureMagFilterValue(context, params))
5958 {
5959 return false;
5960 }
5961 break;
5962
5963 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005964 if (!context->getExtensions().textureUsage)
5965 {
Jamie Madille0472f32018-11-27 16:32:45 -05005966 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Geoff Lang91ab54b2017-10-30 15:12:42 -04005967 return false;
5968 }
5969
Jamie Madillbe849e42017-05-02 15:49:00 -04005970 switch (ConvertToGLenum(params[0]))
5971 {
5972 case GL_NONE:
5973 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5974 break;
5975
5976 default:
Jamie Madille0472f32018-11-27 16:32:45 -05005977 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005978 return false;
5979 }
5980 break;
5981
5982 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005983 {
5984 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5985 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005986 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005987 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005988 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005989 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5990 }
5991 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005992
5993 case GL_TEXTURE_MIN_LOD:
5994 case GL_TEXTURE_MAX_LOD:
5995 // any value is permissible
5996 break;
5997
5998 case GL_TEXTURE_COMPARE_MODE:
5999 if (!ValidateTextureCompareModeValue(context, params))
6000 {
6001 return false;
6002 }
6003 break;
6004
6005 case GL_TEXTURE_COMPARE_FUNC:
6006 if (!ValidateTextureCompareFuncValue(context, params))
6007 {
6008 return false;
6009 }
6010 break;
6011
6012 case GL_TEXTURE_SWIZZLE_R:
6013 case GL_TEXTURE_SWIZZLE_G:
6014 case GL_TEXTURE_SWIZZLE_B:
6015 case GL_TEXTURE_SWIZZLE_A:
6016 switch (ConvertToGLenum(params[0]))
6017 {
6018 case GL_RED:
6019 case GL_GREEN:
6020 case GL_BLUE:
6021 case GL_ALPHA:
6022 case GL_ZERO:
6023 case GL_ONE:
6024 break;
6025
6026 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006027 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006028 return false;
6029 }
6030 break;
6031
6032 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006033 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006034 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006035 context->validationError(GL_INVALID_VALUE, kBaseLevelNegative);
Jamie Madillbe849e42017-05-02 15:49:00 -04006036 return false;
6037 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006038 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006039 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006040 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04006041 return false;
6042 }
Olli Etuahod310a432018-08-24 15:40:23 +03006043 if ((target == TextureType::_2DMultisample ||
6044 target == TextureType::_2DMultisampleArray) &&
6045 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006046 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006047 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
JiangYizhou4cff8d62017-07-06 14:54:09 +08006048 return false;
6049 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006050 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006051 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006052 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006053 return false;
6054 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006055 break;
6056
6057 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006058 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006059 {
Jamie Madille0472f32018-11-27 16:32:45 -05006060 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006061 return false;
6062 }
6063 break;
6064
6065 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6066 if (context->getClientVersion() < Version(3, 1))
6067 {
Jamie Madille0472f32018-11-27 16:32:45 -05006068 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006069 return false;
6070 }
6071 switch (ConvertToGLenum(params[0]))
6072 {
6073 case GL_DEPTH_COMPONENT:
6074 case GL_STENCIL_INDEX:
6075 break;
6076
6077 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006078 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006079 return false;
6080 }
6081 break;
6082
6083 case GL_TEXTURE_SRGB_DECODE_EXT:
6084 if (!ValidateTextureSRGBDecodeValue(context, params))
6085 {
6086 return false;
6087 }
6088 break;
6089
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006090 case GL_GENERATE_MIPMAP:
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006091 if (context->getClientMajorVersion() > 1)
6092 {
Jamie Madille0472f32018-11-27 16:32:45 -05006093 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006094 return false;
6095 }
6096 break;
Till Rathmannb8543632018-10-02 19:46:14 +02006097
6098 case GL_TEXTURE_CROP_RECT_OES:
6099 if (context->getClientMajorVersion() > 1)
6100 {
Jamie Madille0472f32018-11-27 16:32:45 -05006101 context->validationError(GL_INVALID_ENUM, kGLES1Only);
Till Rathmannb8543632018-10-02 19:46:14 +02006102 return false;
6103 }
6104 if (!vectorParams)
6105 {
Jamie Madille0472f32018-11-27 16:32:45 -05006106 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006107 return false;
6108 }
6109 break;
6110
6111 case GL_TEXTURE_BORDER_COLOR:
6112 if (!context->getExtensions().textureBorderClamp)
6113 {
Jamie Madille0472f32018-11-27 16:32:45 -05006114 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006115 return false;
6116 }
6117 if (!vectorParams)
6118 {
Jamie Madille0472f32018-11-27 16:32:45 -05006119 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006120 return false;
6121 }
6122 break;
6123
Jamie Madillbe849e42017-05-02 15:49:00 -04006124 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006125 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006126 return false;
6127 }
6128
6129 return true;
6130}
6131
Till Rathmannb8543632018-10-02 19:46:14 +02006132template bool ValidateTexParameterBase(Context *,
6133 TextureType,
6134 GLenum,
6135 GLsizei,
6136 bool,
6137 const GLfloat *);
6138template bool ValidateTexParameterBase(Context *,
6139 TextureType,
6140 GLenum,
6141 GLsizei,
6142 bool,
6143 const GLint *);
6144template bool ValidateTexParameterBase(Context *,
6145 TextureType,
6146 GLenum,
6147 GLsizei,
6148 bool,
6149 const GLuint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006150
Jamie Madill5b772312018-03-08 20:28:32 -05006151bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006152{
6153 if (index >= MAX_VERTEX_ATTRIBS)
6154 {
Jamie Madille0472f32018-11-27 16:32:45 -05006155 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Jamie Madill12e957f2017-08-26 21:42:26 -04006156 return false;
6157 }
6158
6159 return true;
6160}
6161
6162bool ValidateGetActiveUniformBlockivBase(Context *context,
6163 GLuint program,
6164 GLuint uniformBlockIndex,
6165 GLenum pname,
6166 GLsizei *length)
6167{
6168 if (length)
6169 {
6170 *length = 0;
6171 }
6172
6173 if (context->getClientMajorVersion() < 3)
6174 {
Jamie Madille0472f32018-11-27 16:32:45 -05006175 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill12e957f2017-08-26 21:42:26 -04006176 return false;
6177 }
6178
6179 Program *programObject = GetValidProgram(context, program);
6180 if (!programObject)
6181 {
6182 return false;
6183 }
6184
6185 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6186 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006187 context->validationError(GL_INVALID_VALUE, kIndexExceedsActiveUniformBlockCount);
Jamie Madill12e957f2017-08-26 21:42:26 -04006188 return false;
6189 }
6190
6191 switch (pname)
6192 {
6193 case GL_UNIFORM_BLOCK_BINDING:
6194 case GL_UNIFORM_BLOCK_DATA_SIZE:
6195 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6196 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6197 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6198 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6199 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6200 break;
6201
6202 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006203 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill12e957f2017-08-26 21:42:26 -04006204 return false;
6205 }
6206
6207 if (length)
6208 {
6209 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6210 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006211 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006212 programObject->getUniformBlockByIndex(uniformBlockIndex);
6213 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6214 }
6215 else
6216 {
6217 *length = 1;
6218 }
6219 }
6220
6221 return true;
6222}
6223
Jamie Madill9696d072017-08-26 23:19:57 -04006224template <typename ParamType>
6225bool ValidateSamplerParameterBase(Context *context,
6226 GLuint sampler,
6227 GLenum pname,
6228 GLsizei bufSize,
Till Rathmannb8543632018-10-02 19:46:14 +02006229 bool vectorParams,
Jamie Madill9696d072017-08-26 23:19:57 -04006230 ParamType *params)
6231{
6232 if (context->getClientMajorVersion() < 3)
6233 {
Jamie Madille0472f32018-11-27 16:32:45 -05006234 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006235 return false;
6236 }
6237
6238 if (!context->isSampler(sampler))
6239 {
Jamie Madille0472f32018-11-27 16:32:45 -05006240 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
Jamie Madill9696d072017-08-26 23:19:57 -04006241 return false;
6242 }
6243
Till Rathmannb8543632018-10-02 19:46:14 +02006244 const GLsizei minBufSize = GetSamplerParameterCount(pname);
Jamie Madill9696d072017-08-26 23:19:57 -04006245 if (bufSize >= 0 && bufSize < minBufSize)
6246 {
Jamie Madille0472f32018-11-27 16:32:45 -05006247 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Jamie Madill9696d072017-08-26 23:19:57 -04006248 return false;
6249 }
6250
6251 switch (pname)
6252 {
6253 case GL_TEXTURE_WRAP_S:
6254 case GL_TEXTURE_WRAP_T:
6255 case GL_TEXTURE_WRAP_R:
6256 if (!ValidateTextureWrapModeValue(context, params, false))
6257 {
6258 return false;
6259 }
6260 break;
6261
6262 case GL_TEXTURE_MIN_FILTER:
6263 if (!ValidateTextureMinFilterValue(context, params, false))
6264 {
6265 return false;
6266 }
6267 break;
6268
6269 case GL_TEXTURE_MAG_FILTER:
6270 if (!ValidateTextureMagFilterValue(context, params))
6271 {
6272 return false;
6273 }
6274 break;
6275
6276 case GL_TEXTURE_MIN_LOD:
6277 case GL_TEXTURE_MAX_LOD:
6278 // any value is permissible
6279 break;
6280
6281 case GL_TEXTURE_COMPARE_MODE:
6282 if (!ValidateTextureCompareModeValue(context, params))
6283 {
6284 return false;
6285 }
6286 break;
6287
6288 case GL_TEXTURE_COMPARE_FUNC:
6289 if (!ValidateTextureCompareFuncValue(context, params))
6290 {
6291 return false;
6292 }
6293 break;
6294
6295 case GL_TEXTURE_SRGB_DECODE_EXT:
6296 if (!ValidateTextureSRGBDecodeValue(context, params))
6297 {
6298 return false;
6299 }
6300 break;
6301
Luc Ferron1b1a8642018-01-23 15:12:01 -05006302 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6303 {
6304 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6305 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6306 {
6307 return false;
6308 }
6309 }
6310 break;
6311
Till Rathmannb8543632018-10-02 19:46:14 +02006312 case GL_TEXTURE_BORDER_COLOR:
6313 if (!context->getExtensions().textureBorderClamp)
6314 {
Jamie Madille0472f32018-11-27 16:32:45 -05006315 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006316 return false;
6317 }
6318 if (!vectorParams)
6319 {
Jamie Madille0472f32018-11-27 16:32:45 -05006320 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
Till Rathmannb8543632018-10-02 19:46:14 +02006321 return false;
6322 }
6323 break;
6324
Jamie Madill9696d072017-08-26 23:19:57 -04006325 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006326 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006327 return false;
6328 }
6329
6330 return true;
6331}
6332
Till Rathmannb8543632018-10-02 19:46:14 +02006333template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, bool, GLfloat *);
6334template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, bool, GLint *);
6335template bool ValidateSamplerParameterBase(Context *,
6336 GLuint,
6337 GLenum,
6338 GLsizei,
6339 bool,
6340 const GLuint *);
Jamie Madill9696d072017-08-26 23:19:57 -04006341
6342bool ValidateGetSamplerParameterBase(Context *context,
6343 GLuint sampler,
6344 GLenum pname,
6345 GLsizei *length)
6346{
6347 if (length)
6348 {
6349 *length = 0;
6350 }
6351
6352 if (context->getClientMajorVersion() < 3)
6353 {
Jamie Madille0472f32018-11-27 16:32:45 -05006354 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006355 return false;
6356 }
6357
6358 if (!context->isSampler(sampler))
6359 {
Jamie Madille0472f32018-11-27 16:32:45 -05006360 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
Jamie Madill9696d072017-08-26 23:19:57 -04006361 return false;
6362 }
6363
6364 switch (pname)
6365 {
6366 case GL_TEXTURE_WRAP_S:
6367 case GL_TEXTURE_WRAP_T:
6368 case GL_TEXTURE_WRAP_R:
6369 case GL_TEXTURE_MIN_FILTER:
6370 case GL_TEXTURE_MAG_FILTER:
6371 case GL_TEXTURE_MIN_LOD:
6372 case GL_TEXTURE_MAX_LOD:
6373 case GL_TEXTURE_COMPARE_MODE:
6374 case GL_TEXTURE_COMPARE_FUNC:
6375 break;
6376
Luc Ferron1b1a8642018-01-23 15:12:01 -05006377 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6378 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6379 {
6380 return false;
6381 }
6382 break;
6383
Jamie Madill9696d072017-08-26 23:19:57 -04006384 case GL_TEXTURE_SRGB_DECODE_EXT:
6385 if (!context->getExtensions().textureSRGBDecode)
6386 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006387 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006388 return false;
6389 }
6390 break;
6391
Till Rathmannb8543632018-10-02 19:46:14 +02006392 case GL_TEXTURE_BORDER_COLOR:
6393 if (!context->getExtensions().textureBorderClamp)
6394 {
Jamie Madille0472f32018-11-27 16:32:45 -05006395 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
Till Rathmannb8543632018-10-02 19:46:14 +02006396 return false;
6397 }
6398 break;
6399
Jamie Madill9696d072017-08-26 23:19:57 -04006400 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006401 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006402 return false;
6403 }
6404
6405 if (length)
6406 {
Till Rathmannb8543632018-10-02 19:46:14 +02006407 *length = GetSamplerParameterCount(pname);
Jamie Madill9696d072017-08-26 23:19:57 -04006408 }
6409 return true;
6410}
6411
6412bool ValidateGetInternalFormativBase(Context *context,
6413 GLenum target,
6414 GLenum internalformat,
6415 GLenum pname,
6416 GLsizei bufSize,
6417 GLsizei *numParams)
6418{
6419 if (numParams)
6420 {
6421 *numParams = 0;
6422 }
6423
6424 if (context->getClientMajorVersion() < 3)
6425 {
Jamie Madille0472f32018-11-27 16:32:45 -05006426 context->validationError(GL_INVALID_OPERATION, kES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006427 return false;
6428 }
6429
6430 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006431 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006432 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006433 context->validationError(GL_INVALID_ENUM, kFormatNotRenderable);
Jamie Madill9696d072017-08-26 23:19:57 -04006434 return false;
6435 }
6436
6437 switch (target)
6438 {
6439 case GL_RENDERBUFFER:
6440 break;
6441
6442 case GL_TEXTURE_2D_MULTISAMPLE:
Yizhou Jiang7818a852018-09-06 15:02:04 +08006443 if (context->getClientVersion() < ES_3_1 &&
6444 !context->getExtensions().textureMultisample)
Jamie Madill9696d072017-08-26 23:19:57 -04006445 {
Jamie Madill610640f2018-11-21 17:28:41 -05006446 context->validationError(GL_INVALID_ENUM,
Jamie Madille0472f32018-11-27 16:32:45 -05006447 kMultisampleTextureExtensionOrES31Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006448 return false;
6449 }
6450 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006451 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6452 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006453 {
Jamie Madille0472f32018-11-27 16:32:45 -05006454 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
Olli Etuahod310a432018-08-24 15:40:23 +03006455 return false;
6456 }
6457 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006458 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006459 context->validationError(GL_INVALID_ENUM, kInvalidTarget);
Jamie Madill9696d072017-08-26 23:19:57 -04006460 return false;
6461 }
6462
6463 if (bufSize < 0)
6464 {
Jamie Madille0472f32018-11-27 16:32:45 -05006465 context->validationError(GL_INVALID_VALUE, kInsufficientBufferSize);
Jamie Madill9696d072017-08-26 23:19:57 -04006466 return false;
6467 }
6468
6469 GLsizei maxWriteParams = 0;
6470 switch (pname)
6471 {
6472 case GL_NUM_SAMPLE_COUNTS:
6473 maxWriteParams = 1;
6474 break;
6475
6476 case GL_SAMPLES:
6477 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6478 break;
6479
6480 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006481 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
Jamie Madill9696d072017-08-26 23:19:57 -04006482 return false;
6483 }
6484
6485 if (numParams)
6486 {
6487 // glGetInternalFormativ will not overflow bufSize
6488 *numParams = std::min(bufSize, maxWriteParams);
6489 }
6490
6491 return true;
6492}
6493
Jamie Madille98b1b52018-03-08 09:47:23 -05006494bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6495{
Jamie Madill427064d2018-04-13 16:20:34 -04006496 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006497 {
Jamie Madille0472f32018-11-27 16:32:45 -05006498 context->validationError(GL_INVALID_OPERATION, kInvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006499 return false;
6500 }
6501 return true;
6502}
6503
Lingfeng Yang038dd532018-03-29 17:31:52 -07006504bool ValidateMultitextureUnit(Context *context, GLenum texture)
6505{
6506 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6507 {
Jamie Madille0472f32018-11-27 16:32:45 -05006508 context->validationError(GL_INVALID_ENUM, kInvalidMultitextureUnit);
Lingfeng Yang038dd532018-03-29 17:31:52 -07006509 return false;
6510 }
6511 return true;
6512}
6513
Olli Etuahod310a432018-08-24 15:40:23 +03006514bool ValidateTexStorageMultisample(Context *context,
6515 TextureType target,
6516 GLsizei samples,
6517 GLint internalFormat,
6518 GLsizei width,
6519 GLsizei height)
6520{
6521 const Caps &caps = context->getCaps();
6522 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6523 static_cast<GLuint>(height) > caps.max2DTextureSize)
6524 {
Jamie Madille0472f32018-11-27 16:32:45 -05006525 context->validationError(GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
Olli Etuahod310a432018-08-24 15:40:23 +03006526 return false;
6527 }
6528
6529 if (samples == 0)
6530 {
Jamie Madille0472f32018-11-27 16:32:45 -05006531 context->validationError(GL_INVALID_VALUE, kSamplesZero);
Olli Etuahod310a432018-08-24 15:40:23 +03006532 return false;
6533 }
6534
6535 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6536 if (!formatCaps.textureAttachment)
6537 {
Jamie Madille0472f32018-11-27 16:32:45 -05006538 context->validationError(GL_INVALID_ENUM, kRenderableInternalFormat);
Olli Etuahod310a432018-08-24 15:40:23 +03006539 return false;
6540 }
6541
6542 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6543 // is one of the unsized base internalformats listed in table 8.11.
6544 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6545 if (formatInfo.internalFormat == GL_NONE)
6546 {
Jamie Madille0472f32018-11-27 16:32:45 -05006547 context->validationError(GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
Olli Etuahod310a432018-08-24 15:40:23 +03006548 return false;
6549 }
6550
6551 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6552 {
Jamie Madille0472f32018-11-27 16:32:45 -05006553 context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
Olli Etuahod310a432018-08-24 15:40:23 +03006554 return false;
6555 }
6556
6557 Texture *texture = context->getTargetTexture(target);
6558 if (!texture || texture->id() == 0)
6559 {
Jamie Madille0472f32018-11-27 16:32:45 -05006560 context->validationError(GL_INVALID_OPERATION, kZeroBoundToTarget);
Olli Etuahod310a432018-08-24 15:40:23 +03006561 return false;
6562 }
6563
6564 if (texture->getImmutableFormat())
6565 {
Jamie Madille0472f32018-11-27 16:32:45 -05006566 context->validationError(GL_INVALID_OPERATION, kImmutableTextureBound);
Olli Etuahod310a432018-08-24 15:40:23 +03006567 return false;
6568 }
6569 return true;
6570}
6571
Yizhou Jiang7818a852018-09-06 15:02:04 +08006572bool ValidateTexStorage2DMultisampleBase(Context *context,
6573 TextureType target,
6574 GLsizei samples,
6575 GLint internalFormat,
6576 GLsizei width,
6577 GLsizei height)
6578{
6579 if (target != TextureType::_2DMultisample)
6580 {
Jamie Madille0472f32018-11-27 16:32:45 -05006581 context->validationError(GL_INVALID_ENUM, kInvalidTarget);
Yizhou Jiang7818a852018-09-06 15:02:04 +08006582 return false;
6583 }
6584
6585 if (width < 1 || height < 1)
6586 {
Jamie Madille0472f32018-11-27 16:32:45 -05006587 context->validationError(GL_INVALID_VALUE, kTextureSizeTooSmall);
Yizhou Jiang7818a852018-09-06 15:02:04 +08006588 return false;
6589 }
6590
6591 return ValidateTexStorageMultisample(context, target, samples, internalFormat, width, height);
6592}
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006593
6594bool ValidateGetTexLevelParameterBase(Context *context,
6595 TextureTarget target,
6596 GLint level,
6597 GLenum pname,
6598 GLsizei *length)
6599{
6600
6601 if (length)
6602 {
6603 *length = 0;
6604 }
6605
6606 TextureType type = TextureTargetToType(target);
6607
6608 if (!ValidTexLevelDestinationTarget(context, type))
6609 {
Jamie Madille0472f32018-11-27 16:32:45 -05006610 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006611 return false;
6612 }
6613
6614 if (context->getTargetTexture(type) == nullptr)
6615 {
Jamie Madillc3e37312018-11-30 15:25:39 -05006616 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006617 return false;
6618 }
6619
6620 if (!ValidMipLevel(context, type, level))
6621 {
Jamie Madille0472f32018-11-27 16:32:45 -05006622 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006623 return false;
6624 }
6625
6626 switch (pname)
6627 {
6628 case GL_TEXTURE_RED_TYPE:
6629 case GL_TEXTURE_GREEN_TYPE:
6630 case GL_TEXTURE_BLUE_TYPE:
6631 case GL_TEXTURE_ALPHA_TYPE:
6632 case GL_TEXTURE_DEPTH_TYPE:
6633 break;
6634 case GL_TEXTURE_RED_SIZE:
6635 case GL_TEXTURE_GREEN_SIZE:
6636 case GL_TEXTURE_BLUE_SIZE:
6637 case GL_TEXTURE_ALPHA_SIZE:
6638 case GL_TEXTURE_DEPTH_SIZE:
6639 case GL_TEXTURE_STENCIL_SIZE:
6640 case GL_TEXTURE_SHARED_SIZE:
6641 break;
6642 case GL_TEXTURE_INTERNAL_FORMAT:
6643 case GL_TEXTURE_WIDTH:
6644 case GL_TEXTURE_HEIGHT:
6645 case GL_TEXTURE_DEPTH:
6646 break;
6647 case GL_TEXTURE_SAMPLES:
6648 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
6649 break;
6650 case GL_TEXTURE_COMPRESSED:
6651 break;
6652 default:
Jamie Madille0472f32018-11-27 16:32:45 -05006653 context->validationError(GL_INVALID_ENUM, kInvalidPname);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006654 return false;
6655 }
6656
6657 if (length)
6658 {
6659 *length = 1;
6660 }
6661 return true;
6662}
Yizhou Jiang7310da32018-11-05 14:40:01 +08006663
6664bool ValidateGetMultisamplefvBase(Context *context, GLenum pname, GLuint index, GLfloat *val)
6665{
6666 if (pname != GL_SAMPLE_POSITION)
6667 {
6668 context->validationError(GL_INVALID_ENUM, kInvalidPname);
6669 return false;
6670 }
6671
6672 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
6673 GLint samples = framebuffer->getSamples(context);
6674
6675 if (index >= static_cast<GLuint>(samples))
6676 {
6677 context->validationError(GL_INVALID_VALUE, kIndexExceedsSamples);
6678 return false;
6679 }
6680
6681 return true;
6682}
6683
6684bool ValidateSampleMaskiBase(Context *context, GLuint maskNumber, GLbitfield mask)
6685{
6686 if (maskNumber >= context->getCaps().maxSampleMaskWords)
6687 {
6688 context->validationError(GL_INVALID_VALUE, kInvalidSampleMaskNumber);
6689 return false;
6690 }
6691
6692 return true;
6693}
Jamie Madillc29968b2016-01-20 11:17:23 -05006694} // namespace gl