blob: 99b700964a0f9fc187b18c74ec464a737d35cff2 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Lingfeng Yangf97641c2018-06-21 19:22:45 -070025#include "libANGLE/queryutils.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040026#include "libANGLE/validationES2.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29#include "common/mathutil.h"
30#include "common/utilities.h"
31
Jamie Madille2e406c2016-06-02 13:04:10 -040032using namespace angle;
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034namespace gl
35{
Jamie Madill1ca74672015-07-21 15:14:11 -040036namespace
37{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050038bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
39{
40 // List of compressed format that require that the texture size is smaller than or a multiple of
41 // the compressed block size.
42 switch (internalFormat)
43 {
44 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
46 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
47 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
48 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
52 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
53 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59 return true;
jchen10a99ed552017-09-22 08:10:32 +080060
Luc Ferron9dbaeba2018-02-01 07:26:59 -050061 default:
62 return false;
63 }
64}
65bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
66{
67 // Compressed sub textures have additional formats that requires exact size.
68 // ES 3.1, Section 8.7, Page 171
69 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
70 IsETC2EACFormat(internalFormat);
71}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030072
73bool DifferenceCanOverflow(GLint a, GLint b)
74{
75 CheckedNumeric<GLint> checkedA(a);
76 checkedA -= b;
77 // Use negation to make sure that the difference can't overflow regardless of the order.
78 checkedA = -checkedA;
79 return !checkedA.IsValid();
80}
81
Jamie Madillac43aaa2018-07-31 11:22:13 -040082bool ValidateDrawClientAttribs(Context *context)
83{
Jamie Madill2da53562018-08-01 11:34:47 -040084 ASSERT(context->getStateCache().hasAnyEnabledClientAttrib());
Jamie Madillac43aaa2018-07-31 11:22:13 -040085
Jamie Madill43da7c42018-08-01 11:34:49 -040086 const State &state = context->getGLState();
Jamie Madillac43aaa2018-07-31 11:22:13 -040087
88 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
89 {
90 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
91 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
92 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
93 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
94 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
95 return false;
96 }
97
98 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
99 {
100 // This is an application error that would normally result in a crash, but we catch it
101 // and return an error
102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
103 return false;
104 }
105
106 return true;
107}
108
Jamie Madill2da53562018-08-01 11:34:47 -0400109bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -0400110{
Jamie Madill51af38b2018-04-15 08:50:56 -0400111 // If we're drawing zero vertices, we have enough data.
Jamie Madill2da53562018-08-01 11:34:47 -0400112 ASSERT(primcount > 0);
Jamie Madill51af38b2018-04-15 08:50:56 -0400113
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400114 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
115 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
Jamie Madill1ca74672015-07-21 15:14:11 -0400116 {
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400117 return true;
Jamie Madill02c9c042018-04-17 13:43:48 -0400118 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800119
Jamie Madill88602e62018-08-08 12:49:30 -0400120 // An overflow can happen when adding the offset. Check against a special constant.
121 if (context->getStateCache().getNonInstancedVertexElementLimit() ==
122 VertexAttribute::kIntegerOverflow ||
123 context->getStateCache().getInstancedVertexElementLimit() ==
124 VertexAttribute::kIntegerOverflow)
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400125 {
126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
127 return false;
128 }
129
130 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
131 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
133 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400134}
135
Jamie Madill5b772312018-03-08 20:28:32 -0500136bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400137{
138 switch (type)
139 {
140 // Types referenced in Table 3.4 of the ES 2.0.25 spec
141 case GL_UNSIGNED_BYTE:
142 case GL_UNSIGNED_SHORT_4_4_4_4:
143 case GL_UNSIGNED_SHORT_5_5_5_1:
144 case GL_UNSIGNED_SHORT_5_6_5:
145 return context->getClientVersion() >= ES_2_0;
146
147 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
148 case GL_BYTE:
149 case GL_INT:
150 case GL_SHORT:
151 case GL_UNSIGNED_INT:
152 case GL_UNSIGNED_INT_10F_11F_11F_REV:
153 case GL_UNSIGNED_INT_24_8:
154 case GL_UNSIGNED_INT_2_10_10_10_REV:
155 case GL_UNSIGNED_INT_5_9_9_9_REV:
156 case GL_UNSIGNED_SHORT:
157 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
158 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
159 return context->getClientVersion() >= ES_3_0;
160
161 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400162 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
163 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400164
165 case GL_HALF_FLOAT:
166 return context->getClientVersion() >= ES_3_0 ||
167 context->getExtensions().textureHalfFloat;
168
169 case GL_HALF_FLOAT_OES:
170 return context->getExtensions().colorBufferHalfFloat;
171
172 default:
173 return false;
174 }
175}
176
Jamie Madill5b772312018-03-08 20:28:32 -0500177bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400178{
179 switch (format)
180 {
181 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
182 case GL_RGBA:
183 case GL_RGB:
184 case GL_ALPHA:
185 return context->getClientVersion() >= ES_2_0;
186
187 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
188 case GL_RG:
189 case GL_RED:
190 case GL_RGBA_INTEGER:
191 case GL_RGB_INTEGER:
192 case GL_RG_INTEGER:
193 case GL_RED_INTEGER:
194 return context->getClientVersion() >= ES_3_0;
195
196 case GL_SRGB_ALPHA_EXT:
197 case GL_SRGB_EXT:
198 return context->getExtensions().sRGB;
199
200 case GL_BGRA_EXT:
201 return context->getExtensions().readFormatBGRA;
202
203 default:
204 return false;
205 }
206}
207
Jamie Madill5b772312018-03-08 20:28:32 -0500208bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400209 GLenum framebufferComponentType,
210 GLenum format,
211 GLenum type)
212{
213 switch (framebufferComponentType)
214 {
215 case GL_UNSIGNED_NORMALIZED:
216 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
217 // ReadPixels with BGRA even if the extension is not present
218 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
219 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
220 type == GL_UNSIGNED_BYTE);
221
222 case GL_SIGNED_NORMALIZED:
223 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
224
225 case GL_INT:
226 return (format == GL_RGBA_INTEGER && type == GL_INT);
227
228 case GL_UNSIGNED_INT:
229 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
230
231 case GL_FLOAT:
232 return (format == GL_RGBA && type == GL_FLOAT);
233
234 default:
235 UNREACHABLE();
236 return false;
237 }
238}
239
Geoff Langc1984ed2016-10-07 12:41:00 -0400240template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400241bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400242{
243 switch (ConvertToGLenum(params[0]))
244 {
245 case GL_CLAMP_TO_EDGE:
246 break;
247
248 case GL_REPEAT:
249 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400250 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400251 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400252 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700253 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400254 return false;
255 }
256 break;
257
258 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700259 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400260 return false;
261 }
262
263 return true;
264}
265
266template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400267bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400268{
269 switch (ConvertToGLenum(params[0]))
270 {
271 case GL_NEAREST:
272 case GL_LINEAR:
273 break;
274
275 case GL_NEAREST_MIPMAP_NEAREST:
276 case GL_LINEAR_MIPMAP_NEAREST:
277 case GL_NEAREST_MIPMAP_LINEAR:
278 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400279 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400280 {
281 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700282 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400283 return false;
284 }
285 break;
286
287 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700288 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400289 return false;
290 }
291
292 return true;
293}
294
295template <typename ParamType>
296bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
297{
298 switch (ConvertToGLenum(params[0]))
299 {
300 case GL_NEAREST:
301 case GL_LINEAR:
302 break;
303
304 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 return false;
307 }
308
309 return true;
310}
311
312template <typename ParamType>
313bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
314{
315 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
316 switch (ConvertToGLenum(params[0]))
317 {
318 case GL_NONE:
319 case GL_COMPARE_REF_TO_TEXTURE:
320 break;
321
322 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700323 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400324 return false;
325 }
326
327 return true;
328}
329
330template <typename ParamType>
331bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
332{
333 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
334 switch (ConvertToGLenum(params[0]))
335 {
336 case GL_LEQUAL:
337 case GL_GEQUAL:
338 case GL_LESS:
339 case GL_GREATER:
340 case GL_EQUAL:
341 case GL_NOTEQUAL:
342 case GL_ALWAYS:
343 case GL_NEVER:
344 break;
345
346 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700347 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400348 return false;
349 }
350
351 return true;
352}
353
354template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700355bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
356{
357 if (!context->getExtensions().textureSRGBDecode)
358 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700359 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700360 return false;
361 }
362
363 switch (ConvertToGLenum(params[0]))
364 {
365 case GL_DECODE_EXT:
366 case GL_SKIP_DECODE_EXT:
367 break;
368
369 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700370 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700371 return false;
372 }
373
374 return true;
375}
376
Luc Ferron1b1a8642018-01-23 15:12:01 -0500377bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
378{
379 if (!context->getExtensions().textureFilterAnisotropic)
380 {
381 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
382 return false;
383 }
384
385 return true;
386}
387
388bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
389{
390 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
391 {
392 return false;
393 }
394
395 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
396
397 if (paramValue < 1 || paramValue > largest)
398 {
399 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
400 return false;
401 }
402
403 return true;
404}
405
Jamie Madill5b772312018-03-08 20:28:32 -0500406bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400407{
408 const Program *program = context->getGLState().getProgram();
409 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
410
Brandon Jonesc405ae72017-12-06 14:15:03 -0800411 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
412 framebuffer->getDrawBufferTypeMask().to_ulong(),
413 program->getActiveOutputVariables().to_ulong(),
414 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400415 {
Brandon Jones76746f92017-11-22 11:44:41 -0800416 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
417 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400418 }
419
420 return true;
421}
422
Jamie Madill5b772312018-03-08 20:28:32 -0500423bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400424{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700425 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400426 const Program *program = context->getGLState().getProgram();
427 const VertexArray *vao = context->getGLState().getVertexArray();
428
Brandon Jonesc405ae72017-12-06 14:15:03 -0800429 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
430 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
431 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
432
433 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
434 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
435 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
436
437 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
438 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400439 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800440 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
441 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400442 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400443 return true;
444}
445
Jamie Madill493f9572018-05-24 19:52:15 -0400446bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
447 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800448{
449 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400450 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800451 {
Jamie Madill493f9572018-05-24 19:52:15 -0400452 case PrimitiveMode::Points:
453 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
454 case PrimitiveMode::Lines:
455 case PrimitiveMode::LineStrip:
456 case PrimitiveMode::LineLoop:
457 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
458 case PrimitiveMode::LinesAdjacency:
459 case PrimitiveMode::LineStripAdjacency:
460 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
461 case PrimitiveMode::Triangles:
462 case PrimitiveMode::TriangleFan:
463 case PrimitiveMode::TriangleStrip:
464 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
465 case PrimitiveMode::TrianglesAdjacency:
466 case PrimitiveMode::TriangleStripAdjacency:
467 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800468 default:
469 UNREACHABLE();
470 return false;
471 }
472}
473
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700474// GLES1 texture parameters are a small subset of the others
475bool IsValidGLES1TextureParameter(GLenum pname)
476{
477 switch (pname)
478 {
479 case GL_TEXTURE_MAG_FILTER:
480 case GL_TEXTURE_MIN_FILTER:
481 case GL_TEXTURE_WRAP_S:
482 case GL_TEXTURE_WRAP_T:
483 case GL_TEXTURE_WRAP_R:
484 case GL_GENERATE_MIPMAP:
485 case GL_TEXTURE_CROP_RECT_OES:
486 return true;
487 default:
488 return false;
489 }
490}
491
Geoff Langf41a7152016-09-19 15:11:17 -0400492} // anonymous namespace
493
Brandon Jonesd1049182018-03-28 10:02:20 -0700494void SetRobustLengthParam(GLsizei *length, GLsizei value)
495{
496 if (length)
497 {
498 *length = value;
499 }
500}
501
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500502bool IsETC2EACFormat(const GLenum format)
503{
504 // ES 3.1, Table 8.19
505 switch (format)
506 {
507 case GL_COMPRESSED_R11_EAC:
508 case GL_COMPRESSED_SIGNED_R11_EAC:
509 case GL_COMPRESSED_RG11_EAC:
510 case GL_COMPRESSED_SIGNED_RG11_EAC:
511 case GL_COMPRESSED_RGB8_ETC2:
512 case GL_COMPRESSED_SRGB8_ETC2:
513 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
514 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
515 case GL_COMPRESSED_RGBA8_ETC2_EAC:
516 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
517 return true;
518
519 default:
520 return false;
521 }
522}
523
Jamie Madill5b772312018-03-08 20:28:32 -0500524bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400525{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800526 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400527 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800528 case TextureType::_2D:
529 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800530 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400531
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800532 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400533 return context->getExtensions().textureRectangle;
534
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800535 case TextureType::_3D:
536 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800537 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500538
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800539 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800540 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400541
He Yunchaoced53ae2016-11-29 15:00:51 +0800542 default:
543 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500544 }
Jamie Madill35d15012013-10-07 10:46:37 -0400545}
546
Jamie Madill5b772312018-03-08 20:28:32 -0500547bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500548{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800549 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500550 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800551 case TextureType::_2D:
552 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500553 return true;
554
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800555 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400556 return context->getExtensions().textureRectangle;
557
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500558 default:
559 return false;
560 }
561}
562
Jamie Madill5b772312018-03-08 20:28:32 -0500563bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500564{
565 switch (target)
566 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800567 case TextureType::_3D:
568 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300569 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500570
571 default:
572 return false;
573 }
574}
575
Ian Ewellbda75592016-04-18 17:25:54 -0400576// Most texture GL calls are not compatible with external textures, so we have a separate validation
577// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500578bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400579{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800580 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400581 (context->getExtensions().eglImageExternal ||
582 context->getExtensions().eglStreamConsumerExternal);
583}
584
Shannon Woods4dfed832014-03-17 20:03:39 -0400585// This function differs from ValidTextureTarget in that the target must be
586// usable as the destination of a 2D operation-- so a cube face is valid, but
587// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400588// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500589bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400590{
591 switch (target)
592 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800593 case TextureTarget::_2D:
594 case TextureTarget::CubeMapNegativeX:
595 case TextureTarget::CubeMapNegativeY:
596 case TextureTarget::CubeMapNegativeZ:
597 case TextureTarget::CubeMapPositiveX:
598 case TextureTarget::CubeMapPositiveY:
599 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800600 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800601 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400602 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800603 default:
604 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500605 }
606}
607
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800608bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400609 PrimitiveMode transformFeedbackPrimitiveMode,
610 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800611{
612 ASSERT(context);
613
614 if (!context->getExtensions().geometryShader)
615 {
616 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
617 // that does not match the current transform feedback object's draw mode (if transform
618 // feedback is active), (3.0.2, section 2.14, pg 86)
619 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
620 }
621
622 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400623 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800624 {
Jamie Madill493f9572018-05-24 19:52:15 -0400625 case PrimitiveMode::Points:
626 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
627 case PrimitiveMode::Lines:
628 case PrimitiveMode::LineStrip:
629 case PrimitiveMode::LineLoop:
630 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
631 case PrimitiveMode::Triangles:
632 case PrimitiveMode::TriangleFan:
633 case PrimitiveMode::TriangleStrip:
634 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800635 default:
636 UNREACHABLE();
637 return false;
638 }
639}
640
Jamie Madill5b772312018-03-08 20:28:32 -0500641bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400642 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400643 GLsizei count,
644 GLenum type,
645 const GLvoid *indices,
646 GLsizei primcount)
647{
648 if (primcount < 0)
649 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700650 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400651 return false;
652 }
653
654 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
655 {
656 return false;
657 }
658
Jamie Madill9fdaa492018-02-16 10:52:11 -0500659 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400660}
661
662bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400663 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400664 GLint first,
665 GLsizei count,
666 GLsizei primcount)
667{
668 if (primcount < 0)
669 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700670 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400671 return false;
672 }
673
674 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
675 {
676 return false;
677 }
678
Jamie Madill9fdaa492018-02-16 10:52:11 -0500679 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400680}
681
Jamie Madill5b772312018-03-08 20:28:32 -0500682bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400683{
684 // Verify there is at least one active attribute with a divisor of zero
685 const State &state = context->getGLState();
686
687 Program *program = state.getProgram();
688
689 const auto &attribs = state.getVertexArray()->getVertexAttributes();
690 const auto &bindings = state.getVertexArray()->getVertexBindings();
691 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
692 {
693 const VertexAttribute &attrib = attribs[attributeIndex];
694 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300695 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400696 {
697 return true;
698 }
699 }
700
Brandon Jonesafa75152017-07-21 13:11:29 -0700701 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400702 return false;
703}
704
Jamie Madill5b772312018-03-08 20:28:32 -0500705bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500706{
707 switch (target)
708 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800709 case TextureType::_3D:
710 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800711 return true;
712 default:
713 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400714 }
715}
716
Jamie Madill5b772312018-03-08 20:28:32 -0500717bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800718{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800719 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800720 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800721 case TextureType::_2D:
722 case TextureType::_2DArray:
723 case TextureType::_2DMultisample:
724 case TextureType::CubeMap:
725 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800726 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800727 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400728 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800729 default:
730 return false;
731 }
732}
733
Jamie Madill5b772312018-03-08 20:28:32 -0500734bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500735{
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
737 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400738 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500739
740 switch (target)
741 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800742 case GL_FRAMEBUFFER:
743 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400744
He Yunchaoced53ae2016-11-29 15:00:51 +0800745 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800746 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400747 return (context->getExtensions().framebufferBlit ||
748 context->getClientMajorVersion() >= 3);
749
He Yunchaoced53ae2016-11-29 15:00:51 +0800750 default:
751 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500752 }
753}
754
Jamie Madill5b772312018-03-08 20:28:32 -0500755bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400756{
Jamie Madillc29968b2016-01-20 11:17:23 -0500757 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400758 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800759 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400760 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800761 case TextureType::_2D:
762 case TextureType::_2DArray:
763 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500764 maxDimension = caps.max2DTextureSize;
765 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800766 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800767 maxDimension = caps.maxCubeMapTextureSize;
768 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800769 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400770 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800771 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800772 maxDimension = caps.max3DTextureSize;
773 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800774 default:
775 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400776 }
777
Jamie Madill43da7c42018-08-01 11:34:49 -0400778 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400779}
780
Jamie Madill5b772312018-03-08 20:28:32 -0500781bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800782 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700783 GLint level,
784 GLsizei width,
785 GLsizei height,
786 GLsizei depth,
787 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400788{
Brandon Jones6cad5662017-06-14 13:25:13 -0700789 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400790 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700791 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400792 return false;
793 }
Austin Kinross08528e12015-10-07 16:24:40 -0700794 // TexSubImage parameters can be NPOT without textureNPOT extension,
795 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500796 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500797 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500798 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400799 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400800 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700801 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400802 return false;
803 }
804
805 if (!ValidMipLevel(context, target, level))
806 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700807 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400808 return false;
809 }
810
811 return true;
812}
813
Geoff Lang966c9402017-04-18 12:38:27 -0400814bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
815{
816 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
817 (size % blockSize == 0);
818}
819
Jamie Madill5b772312018-03-08 20:28:32 -0500820bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500821 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400822 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500823 GLsizei width,
824 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400825{
Jamie Madill43da7c42018-08-01 11:34:49 -0400826 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400827 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400828 {
829 return false;
830 }
831
Geoff Lang966c9402017-04-18 12:38:27 -0400832 if (width < 0 || height < 0)
833 {
834 return false;
835 }
836
837 if (CompressedTextureFormatRequiresExactSize(internalFormat))
838 {
839 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
840 // block size for level 0 but WebGL disallows this.
841 bool smallerThanBlockSizeAllowed =
842 level > 0 || !context->getExtensions().webglCompatibility;
843
844 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
845 smallerThanBlockSizeAllowed) ||
846 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
847 smallerThanBlockSizeAllowed))
848 {
849 return false;
850 }
851 }
852
853 return true;
854}
855
Jamie Madill5b772312018-03-08 20:28:32 -0500856bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400857 GLenum internalFormat,
858 GLint xoffset,
859 GLint yoffset,
860 GLsizei width,
861 GLsizei height,
862 size_t textureWidth,
863 size_t textureHeight)
864{
Jamie Madill43da7c42018-08-01 11:34:49 -0400865 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400866 if (!formatInfo.compressed)
867 {
868 return false;
869 }
870
Geoff Lang44ff5a72017-02-03 15:15:43 -0500871 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400872 {
873 return false;
874 }
875
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500876 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400877 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500878 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400879 yoffset % formatInfo.compressedBlockHeight != 0)
880 {
881 return false;
882 }
883
884 // Allowed to either have data that is a multiple of block size or is smaller than the block
885 // size but fills the entire mip
886 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
887 static_cast<size_t>(width) == textureWidth &&
888 static_cast<size_t>(height) == textureHeight;
889 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
890 (height % formatInfo.compressedBlockHeight) == 0;
891 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400892 {
893 return false;
894 }
895 }
896
Geoff Langd4f180b2013-09-24 13:57:44 -0400897 return true;
898}
899
Jamie Madill5b772312018-03-08 20:28:32 -0500900bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800901 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400902 GLsizei width,
903 GLsizei height,
904 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400905 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400906 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400907 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400908 GLsizei imageSize)
909{
Jamie Madill43da7c42018-08-01 11:34:49 -0400910 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400911 if (pixelUnpackBuffer == nullptr && imageSize < 0)
912 {
913 // Checks are not required
914 return true;
915 }
916
917 // ...the data would be unpacked from the buffer object such that the memory reads required
918 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400919 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400920 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400921 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400922 const auto &unpack = context->getGLState().getUnpackState();
923
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800924 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400925 GLuint endByte = 0;
926 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400927 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400928 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400929 return false;
930 }
931
Geoff Langff5b2d52016-09-07 11:32:23 -0400932 if (pixelUnpackBuffer)
933 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400934 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400935 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
936 checkedEndByte += checkedOffset;
937
938 if (!checkedEndByte.IsValid() ||
939 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
940 {
941 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400942 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400943 return false;
944 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800945 if (context->getExtensions().webglCompatibility &&
946 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
947 {
948 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
949 PixelUnpackBufferBoundForTransformFeedback);
950 return false;
951 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400952 }
953 else
954 {
955 ASSERT(imageSize >= 0);
956 if (pixels == nullptr && imageSize != 0)
957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500958 context->handleError(InvalidOperation()
959 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400960 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400961 }
962
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400963 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500965 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400966 return false;
967 }
968 }
969
970 return true;
971}
972
Corentin Wallezad3ae902018-03-09 13:40:42 -0500973bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500974{
Geoff Lang37dde692014-01-31 16:34:54 -0500975 switch (queryType)
976 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500977 case QueryType::AnySamples:
978 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400979 return context->getClientMajorVersion() >= 3 ||
980 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500981 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500983 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800984 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500985 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800986 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500987 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800988 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800989 default:
990 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500991 }
992}
993
Jamie Madill5b772312018-03-08 20:28:32 -0500994bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400995 GLenum type,
996 GLboolean normalized,
997 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400998 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400999 bool pureInteger)
1000{
1001 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001002 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1003 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1004 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1005 // parameter exceeds 255.
1006 constexpr GLsizei kMaxWebGLStride = 255;
1007 if (stride > kMaxWebGLStride)
1008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001009 context->handleError(InvalidValue()
1010 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001011 return false;
1012 }
1013
1014 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1015 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1016 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1017 // or an INVALID_OPERATION error is generated.
1018 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1019 size_t typeSize = GetVertexFormatTypeSize(internalType);
1020
1021 ASSERT(isPow2(typeSize) && typeSize > 0);
1022 size_t sizeMask = (typeSize - 1);
1023 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1024 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001025 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001026 return false;
1027 }
1028
1029 if ((stride & sizeMask) != 0)
1030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001032 return false;
1033 }
1034
1035 return true;
1036}
1037
Jamie Madill5b772312018-03-08 20:28:32 -05001038Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001039{
He Yunchaoced53ae2016-11-29 15:00:51 +08001040 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1041 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1042 // or program object and INVALID_OPERATION if the provided name identifies an object
1043 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001044
Dian Xiang769769a2015-09-09 15:20:08 -07001045 Program *validProgram = context->getProgram(id);
1046
1047 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001048 {
Dian Xiang769769a2015-09-09 15:20:08 -07001049 if (context->getShader(id))
1050 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001051 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001052 }
1053 else
1054 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001055 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001056 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001057 }
Dian Xiang769769a2015-09-09 15:20:08 -07001058
1059 return validProgram;
1060}
1061
Jamie Madill5b772312018-03-08 20:28:32 -05001062Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001063{
1064 // See ValidProgram for spec details.
1065
1066 Shader *validShader = context->getShader(id);
1067
1068 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001069 {
Dian Xiang769769a2015-09-09 15:20:08 -07001070 if (context->getProgram(id))
1071 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001072 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001073 }
1074 else
1075 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001076 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001077 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001078 }
Dian Xiang769769a2015-09-09 15:20:08 -07001079
1080 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001081}
1082
Jamie Madill43da7c42018-08-01 11:34:49 -04001083bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001084{
Geoff Langfa125c92017-10-24 13:01:46 -04001085 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001086 {
Geoff Langfa125c92017-10-24 13:01:46 -04001087 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1088 {
1089 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1090 return false;
1091 }
Jamie Madillb4472272014-07-03 10:38:55 -04001092
Geoff Langfa125c92017-10-24 13:01:46 -04001093 // Color attachment 0 is validated below because it is always valid
1094 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001095 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001096 {
Geoff Langfa125c92017-10-24 13:01:46 -04001097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001098 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001099 }
1100 }
1101 else
1102 {
1103 switch (attachment)
1104 {
Geoff Langfa125c92017-10-24 13:01:46 -04001105 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001106 case GL_DEPTH_ATTACHMENT:
1107 case GL_STENCIL_ATTACHMENT:
1108 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001109
He Yunchaoced53ae2016-11-29 15:00:51 +08001110 case GL_DEPTH_STENCIL_ATTACHMENT:
1111 if (!context->getExtensions().webglCompatibility &&
1112 context->getClientMajorVersion() < 3)
1113 {
Geoff Langfa125c92017-10-24 13:01:46 -04001114 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001115 return false;
1116 }
1117 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001118
He Yunchaoced53ae2016-11-29 15:00:51 +08001119 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001120 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001121 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001122 }
1123 }
1124
1125 return true;
1126}
1127
Jamie Madill5b772312018-03-08 20:28:32 -05001128bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001129 GLenum target,
1130 GLsizei samples,
1131 GLenum internalformat,
1132 GLsizei width,
1133 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001134{
1135 switch (target)
1136 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001137 case GL_RENDERBUFFER:
1138 break;
1139 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001140 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001141 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001142 }
1143
1144 if (width < 0 || height < 0 || samples < 0)
1145 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001146 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001147 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001148 }
1149
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001150 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1151 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1152
1153 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001154 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001156 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001158 }
1159
1160 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1161 // 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 -08001162 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001163 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001164 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001165 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001166 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001167 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001168 }
1169
Geoff Langaae65a42014-05-26 12:43:44 -04001170 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001172 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001173 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001174 }
1175
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001176 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001177 if (handle == 0)
1178 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001180 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001181 }
1182
1183 return true;
1184}
1185
Jamie Madill43da7c42018-08-01 11:34:49 -04001186bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001187 GLenum target,
1188 GLenum attachment,
1189 GLenum renderbuffertarget,
1190 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001191{
Geoff Lange8afa902017-09-27 15:00:43 -04001192 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001194 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001195 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001196 }
1197
Jamie Madill43da7c42018-08-01 11:34:49 -04001198 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001199
Jamie Madill84115c92015-04-23 15:00:07 -04001200 ASSERT(framebuffer);
1201 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001202 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001204 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001205 }
1206
Jamie Madillb4472272014-07-03 10:38:55 -04001207 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001208 {
Jamie Madillb4472272014-07-03 10:38:55 -04001209 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001210 }
1211
Jamie Madillab9d82c2014-01-21 16:38:14 -05001212 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1213 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1214 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1215 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1216 if (renderbuffer != 0)
1217 {
1218 if (!context->getRenderbuffer(renderbuffer))
1219 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001220 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001221 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001222 }
1223 }
1224
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001225 return true;
1226}
1227
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001228bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001229 GLint srcX0,
1230 GLint srcY0,
1231 GLint srcX1,
1232 GLint srcY1,
1233 GLint dstX0,
1234 GLint dstY0,
1235 GLint dstX1,
1236 GLint dstY1,
1237 GLbitfield mask,
1238 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001239{
1240 switch (filter)
1241 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001242 case GL_NEAREST:
1243 break;
1244 case GL_LINEAR:
1245 break;
1246 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001247 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001249 }
1250
1251 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001253 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001254 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001255 }
1256
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1258 // color buffer, leaving only nearest being unfiltered from above
1259 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001261 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001262 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001263 }
1264
Jamie Madill51f40ec2016-06-15 14:06:00 -04001265 const auto &glState = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04001266 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1267 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001268
1269 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001271 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001272 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001273 }
1274
Jamie Madill427064d2018-04-13 16:20:34 -04001275 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001276 {
Jamie Madill48faf802014-11-06 15:27:22 -05001277 return false;
1278 }
1279
Jamie Madill427064d2018-04-13 16:20:34 -04001280 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001281 {
Jamie Madill48faf802014-11-06 15:27:22 -05001282 return false;
1283 }
1284
Qin Jiajiaaef92162018-02-27 13:51:44 +08001285 if (readFramebuffer->id() == drawFramebuffer->id())
1286 {
1287 context->handleError(InvalidOperation());
1288 return false;
1289 }
1290
Jamie Madille98b1b52018-03-08 09:47:23 -05001291 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001292 {
Geoff Langb1196682014-07-23 13:47:29 -04001293 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001294 }
1295
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001296 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1297 // always run it in order to avoid triggering driver bugs.
1298 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1299 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001300 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001301 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1302 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001303 }
1304
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1306
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001307 if (mask & GL_COLOR_BUFFER_BIT)
1308 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001309 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001310 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001311
He Yunchao66a41a22016-12-15 16:45:05 +08001312 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001313 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001314 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001315
Geoff Langa15472a2015-08-11 11:48:03 -04001316 for (size_t drawbufferIdx = 0;
1317 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001318 {
Geoff Langa15472a2015-08-11 11:48:03 -04001319 const FramebufferAttachment *attachment =
1320 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1321 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001322 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001323 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001324
Geoff Langb2f3d052013-08-13 12:49:27 -04001325 // The GL ES 3.0.2 spec (pg 193) states that:
1326 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001327 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1328 // as well
1329 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1330 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001331 // Changes with EXT_color_buffer_float:
1332 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001333 GLenum readComponentType = readFormat.info->componentType;
1334 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001335 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001336 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001337 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001338 drawComponentType == GL_SIGNED_NORMALIZED);
1339
1340 if (extensions.colorBufferFloat)
1341 {
1342 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1343 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1344
1345 if (readFixedOrFloat != drawFixedOrFloat)
1346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001347 context->handleError(InvalidOperation()
1348 << "If the read buffer contains fixed-point or "
1349 "floating-point values, the draw buffer must "
1350 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001351 return false;
1352 }
1353 }
1354 else if (readFixedPoint != drawFixedPoint)
1355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001356 context->handleError(InvalidOperation()
1357 << "If the read buffer contains fixed-point values, "
1358 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001359 return false;
1360 }
1361
1362 if (readComponentType == GL_UNSIGNED_INT &&
1363 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001365 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001366 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 }
1368
Jamie Madill6163c752015-12-07 16:32:59 -05001369 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001372 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373 }
1374
Jamie Madilla3944d42016-07-22 22:13:26 -04001375 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001376 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001379 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 }
Geoff Lange4915782017-04-12 15:19:07 -04001381
1382 if (context->getExtensions().webglCompatibility &&
1383 *readColorBuffer == *attachment)
1384 {
1385 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001386 InvalidOperation()
1387 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001388 return false;
1389 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 }
1391 }
1392
Jamie Madilla3944d42016-07-22 22:13:26 -04001393 if ((readFormat.info->componentType == GL_INT ||
1394 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1395 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001398 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400 }
He Yunchao66a41a22016-12-15 16:45:05 +08001401 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1402 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1403 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1404 // situation is an application error that would lead to a crash in ANGLE.
1405 else if (drawFramebuffer->hasEnabledDrawBuffer())
1406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001407 context->handleError(
1408 InvalidOperation()
1409 << "Attempt to read from a missing color attachment of a complete framebuffer.");
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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001429 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001430 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001431 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001433 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001435 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001436 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001437 }
Geoff Lange4915782017-04-12 15:19:07 -04001438
1439 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001441 context->handleError(
1442 InvalidOperation()
1443 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001444 return false;
1445 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001446 }
He Yunchao66a41a22016-12-15 16:45:05 +08001447 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1448 else if (drawBuffer)
1449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001450 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1451 "depth/stencil attachment of a "
1452 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001453 return false;
1454 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001455 }
1456 }
1457
Martin Radeva3ed4572017-07-27 18:29:37 +03001458 // ANGLE_multiview, Revision 1:
1459 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001460 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1461 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1462 // views in the current read framebuffer is more than one.
1463 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001464 {
1465 context->handleError(InvalidFramebufferOperation()
1466 << "Attempt to read from a multi-view framebuffer.");
1467 return false;
1468 }
1469 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1470 {
1471 context->handleError(InvalidFramebufferOperation()
1472 << "Attempt to write to a multi-view framebuffer.");
1473 return false;
1474 }
1475
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001476 return true;
1477}
1478
Jamie Madill4928b7c2017-06-20 12:57:39 -04001479bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001480 GLint x,
1481 GLint y,
1482 GLsizei width,
1483 GLsizei height,
1484 GLenum format,
1485 GLenum type,
1486 GLsizei bufSize,
1487 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001488 GLsizei *columns,
1489 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001490 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001491{
1492 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001494 return false;
1495 }
1496
Brandon Jonesd1049182018-03-28 10:02:20 -07001497 GLsizei writeLength = 0;
1498 GLsizei writeColumns = 0;
1499 GLsizei writeRows = 0;
1500
1501 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1502 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001503 {
Geoff Langb1196682014-07-23 13:47:29 -04001504 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001505 }
1506
Brandon Jonesd1049182018-03-28 10:02:20 -07001507 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001508 {
Geoff Langb1196682014-07-23 13:47:29 -04001509 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001510 }
1511
Brandon Jonesd1049182018-03-28 10:02:20 -07001512 SetRobustLengthParam(length, writeLength);
1513 SetRobustLengthParam(columns, writeColumns);
1514 SetRobustLengthParam(rows, writeRows);
1515
Jamie Madillc29968b2016-01-20 11:17:23 -05001516 return true;
1517}
1518
1519bool ValidateReadnPixelsEXT(Context *context,
1520 GLint x,
1521 GLint y,
1522 GLsizei width,
1523 GLsizei height,
1524 GLenum format,
1525 GLenum type,
1526 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001527 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001528{
1529 if (bufSize < 0)
1530 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001531 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001532 return false;
1533 }
1534
Geoff Lang62fce5b2016-09-30 10:46:35 -04001535 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001536 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001537}
Jamie Madill26e91952014-03-05 15:01:27 -05001538
Jamie Madill4928b7c2017-06-20 12:57:39 -04001539bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001540 GLint x,
1541 GLint y,
1542 GLsizei width,
1543 GLsizei height,
1544 GLenum format,
1545 GLenum type,
1546 GLsizei bufSize,
1547 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001548 GLsizei *columns,
1549 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001550 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001551{
Brandon Jonesd1049182018-03-28 10:02:20 -07001552 GLsizei writeLength = 0;
1553 GLsizei writeColumns = 0;
1554 GLsizei writeRows = 0;
1555
Geoff Lang62fce5b2016-09-30 10:46:35 -04001556 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001557 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001558 return false;
1559 }
1560
Brandon Jonesd1049182018-03-28 10:02:20 -07001561 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1562 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001563 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001564 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001565 }
1566
Brandon Jonesd1049182018-03-28 10:02:20 -07001567 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001568 {
1569 return false;
1570 }
1571
Brandon Jonesd1049182018-03-28 10:02:20 -07001572 SetRobustLengthParam(length, writeLength);
1573 SetRobustLengthParam(columns, writeColumns);
1574 SetRobustLengthParam(rows, writeRows);
1575
Geoff Lang62fce5b2016-09-30 10:46:35 -04001576 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001577}
1578
Jamie Madill43da7c42018-08-01 11:34:49 -04001579bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001580{
1581 if (!context->getExtensions().occlusionQueryBoolean &&
1582 !context->getExtensions().disjointTimerQuery)
1583 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001584 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001585 return false;
1586 }
1587
Olli Etuaho41997e72016-03-10 13:38:39 +02001588 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001589}
1590
Jamie Madill43da7c42018-08-01 11:34:49 -04001591bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001592{
1593 if (!context->getExtensions().occlusionQueryBoolean &&
1594 !context->getExtensions().disjointTimerQuery)
1595 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001597 return false;
1598 }
1599
Olli Etuaho41997e72016-03-10 13:38:39 +02001600 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001601}
1602
Jamie Madill43da7c42018-08-01 11:34:49 -04001603bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001604{
1605 if (!context->getExtensions().occlusionQueryBoolean &&
1606 !context->getExtensions().disjointTimerQuery)
1607 {
1608 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1609 return false;
1610 }
1611
1612 return true;
1613}
1614
Jamie Madill43da7c42018-08-01 11:34:49 -04001615bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001616{
1617 if (!ValidQueryType(context, target))
1618 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001619 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001620 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001621 }
1622
1623 if (id == 0)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001627 }
1628
1629 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1630 // of zero, if the active query object name for <target> is non-zero (for the
1631 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1632 // the active query for either target is non-zero), if <id> is the name of an
1633 // existing query object whose type does not match <target>, or if <id> is the
1634 // active query object name for any query type, the error INVALID_OPERATION is
1635 // generated.
1636
1637 // Ensure no other queries are active
1638 // NOTE: If other queries than occlusion are supported, we will need to check
1639 // separately that:
1640 // a) The query ID passed is not the current active query for any target/type
1641 // b) There are no active queries for the requested target (and in the case
1642 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1643 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001644
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001645 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001648 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001649 }
1650
1651 Query *queryObject = context->getQuery(id, true, target);
1652
1653 // check that name was obtained with glGenQueries
1654 if (!queryObject)
1655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001657 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001658 }
1659
1660 // check for type mismatch
1661 if (queryObject->getType() != target)
1662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001663 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001664 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001665 }
1666
1667 return true;
1668}
1669
Jamie Madill43da7c42018-08-01 11:34:49 -04001670bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671{
1672 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001673 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001674 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001675 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001676 return false;
1677 }
1678
1679 return ValidateBeginQueryBase(context, target, id);
1680}
1681
Jamie Madill43da7c42018-08-01 11:34:49 -04001682bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001683{
1684 if (!ValidQueryType(context, target))
1685 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001686 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001687 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001688 }
1689
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001690 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001691
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001692 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001694 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001695 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001696 }
1697
Jamie Madill45c785d2014-05-13 14:09:34 -04001698 return true;
1699}
1700
Jamie Madill43da7c42018-08-01 11:34:49 -04001701bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702{
1703 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001704 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001706 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001707 return false;
1708 }
1709
1710 return ValidateEndQueryBase(context, target);
1711}
1712
Corentin Wallezad3ae902018-03-09 13:40:42 -05001713bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001714{
1715 if (!context->getExtensions().disjointTimerQuery)
1716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001717 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001718 return false;
1719 }
1720
Corentin Wallezad3ae902018-03-09 13:40:42 -05001721 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001723 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001724 return false;
1725 }
1726
1727 Query *queryObject = context->getQuery(id, true, target);
1728 if (queryObject == nullptr)
1729 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001730 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 return false;
1732 }
1733
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001734 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001735 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001736 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 return false;
1738 }
1739
1740 return true;
1741}
1742
Corentin Wallezad3ae902018-03-09 13:40:42 -05001743bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744{
Geoff Lang2186c382016-10-14 10:54:54 -04001745 if (numParams)
1746 {
1747 *numParams = 0;
1748 }
1749
Corentin Wallezad3ae902018-03-09 13:40:42 -05001750 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001751 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 return false;
1754 }
1755
1756 switch (pname)
1757 {
1758 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001759 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001761 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001762 return false;
1763 }
1764 break;
1765 case GL_QUERY_COUNTER_BITS_EXT:
1766 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001767 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001768 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001769 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770 return false;
1771 }
1772 break;
1773 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001774 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001775 return false;
1776 }
1777
Geoff Lang2186c382016-10-14 10:54:54 -04001778 if (numParams)
1779 {
1780 // All queries return only one value
1781 *numParams = 1;
1782 }
1783
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001784 return true;
1785}
1786
Corentin Wallezad3ae902018-03-09 13:40:42 -05001787bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788{
1789 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001790 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001791 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001792 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001793 return false;
1794 }
1795
Geoff Lang2186c382016-10-14 10:54:54 -04001796 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001797}
1798
Geoff Lang2186c382016-10-14 10:54:54 -04001799bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001800 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001801 GLenum pname,
1802 GLsizei bufSize,
1803 GLsizei *length,
1804 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001805{
Geoff Lang2186c382016-10-14 10:54:54 -04001806 if (!ValidateRobustEntryPoint(context, bufSize))
1807 {
1808 return false;
1809 }
1810
Brandon Jonesd1049182018-03-28 10:02:20 -07001811 GLsizei numParams = 0;
1812
1813 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001814 {
1815 return false;
1816 }
1817
Brandon Jonesd1049182018-03-28 10:02:20 -07001818 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001819 {
1820 return false;
1821 }
1822
Brandon Jonesd1049182018-03-28 10:02:20 -07001823 SetRobustLengthParam(length, numParams);
1824
Geoff Lang2186c382016-10-14 10:54:54 -04001825 return true;
1826}
1827
1828bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1829{
1830 if (numParams)
1831 {
1832 *numParams = 0;
1833 }
1834
Corentin Wallezad3ae902018-03-09 13:40:42 -05001835 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001836
1837 if (!queryObject)
1838 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001839 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001840 return false;
1841 }
1842
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001843 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001844 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001845 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001846 return false;
1847 }
1848
1849 switch (pname)
1850 {
1851 case GL_QUERY_RESULT_EXT:
1852 case GL_QUERY_RESULT_AVAILABLE_EXT:
1853 break;
1854
1855 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001856 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001857 return false;
1858 }
1859
Geoff Lang2186c382016-10-14 10:54:54 -04001860 if (numParams)
1861 {
1862 *numParams = 1;
1863 }
1864
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865 return true;
1866}
1867
1868bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1869{
1870 if (!context->getExtensions().disjointTimerQuery)
1871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001872 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873 return false;
1874 }
Geoff Lang2186c382016-10-14 10:54:54 -04001875 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1876}
1877
1878bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1879 GLuint id,
1880 GLenum pname,
1881 GLsizei bufSize,
1882 GLsizei *length,
1883 GLint *params)
1884{
1885 if (!context->getExtensions().disjointTimerQuery)
1886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001887 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001888 return false;
1889 }
1890
1891 if (!ValidateRobustEntryPoint(context, bufSize))
1892 {
1893 return false;
1894 }
1895
Brandon Jonesd1049182018-03-28 10:02:20 -07001896 GLsizei numParams = 0;
1897
1898 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001899 {
1900 return false;
1901 }
1902
Brandon Jonesd1049182018-03-28 10:02:20 -07001903 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001904 {
1905 return false;
1906 }
1907
Brandon Jonesd1049182018-03-28 10:02:20 -07001908 SetRobustLengthParam(length, numParams);
1909
Geoff Lang2186c382016-10-14 10:54:54 -04001910 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001911}
1912
1913bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1914{
1915 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001916 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001917 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001918 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919 return false;
1920 }
Geoff Lang2186c382016-10-14 10:54:54 -04001921 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1922}
1923
1924bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1925 GLuint id,
1926 GLenum pname,
1927 GLsizei bufSize,
1928 GLsizei *length,
1929 GLuint *params)
1930{
1931 if (!context->getExtensions().disjointTimerQuery &&
1932 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1933 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001934 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001935 return false;
1936 }
1937
1938 if (!ValidateRobustEntryPoint(context, bufSize))
1939 {
1940 return false;
1941 }
1942
Brandon Jonesd1049182018-03-28 10:02:20 -07001943 GLsizei numParams = 0;
1944
1945 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001946 {
1947 return false;
1948 }
1949
Brandon Jonesd1049182018-03-28 10:02:20 -07001950 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001951 {
1952 return false;
1953 }
1954
Brandon Jonesd1049182018-03-28 10:02:20 -07001955 SetRobustLengthParam(length, numParams);
1956
Geoff Lang2186c382016-10-14 10:54:54 -04001957 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001958}
1959
1960bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1961{
1962 if (!context->getExtensions().disjointTimerQuery)
1963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001965 return false;
1966 }
Geoff Lang2186c382016-10-14 10:54:54 -04001967 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1968}
1969
1970bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1971 GLuint id,
1972 GLenum pname,
1973 GLsizei bufSize,
1974 GLsizei *length,
1975 GLint64 *params)
1976{
1977 if (!context->getExtensions().disjointTimerQuery)
1978 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001979 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001980 return false;
1981 }
1982
1983 if (!ValidateRobustEntryPoint(context, bufSize))
1984 {
1985 return false;
1986 }
1987
Brandon Jonesd1049182018-03-28 10:02:20 -07001988 GLsizei numParams = 0;
1989
1990 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001991 {
1992 return false;
1993 }
1994
Brandon Jonesd1049182018-03-28 10:02:20 -07001995 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001996 {
1997 return false;
1998 }
1999
Brandon Jonesd1049182018-03-28 10:02:20 -07002000 SetRobustLengthParam(length, numParams);
2001
Geoff Lang2186c382016-10-14 10:54:54 -04002002 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002003}
2004
2005bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2006{
2007 if (!context->getExtensions().disjointTimerQuery)
2008 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002009 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010 return false;
2011 }
Geoff Lang2186c382016-10-14 10:54:54 -04002012 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2013}
2014
2015bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2016 GLuint id,
2017 GLenum pname,
2018 GLsizei bufSize,
2019 GLsizei *length,
2020 GLuint64 *params)
2021{
2022 if (!context->getExtensions().disjointTimerQuery)
2023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002024 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002025 return false;
2026 }
2027
2028 if (!ValidateRobustEntryPoint(context, bufSize))
2029 {
2030 return false;
2031 }
2032
Brandon Jonesd1049182018-03-28 10:02:20 -07002033 GLsizei numParams = 0;
2034
2035 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002036 {
2037 return false;
2038 }
2039
Brandon Jonesd1049182018-03-28 10:02:20 -07002040 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002041 {
2042 return false;
2043 }
2044
Brandon Jonesd1049182018-03-28 10:02:20 -07002045 SetRobustLengthParam(length, numParams);
2046
Geoff Lang2186c382016-10-14 10:54:54 -04002047 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002048}
2049
Jamie Madill5b772312018-03-08 20:28:32 -05002050bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002051 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002052 GLint location,
2053 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002054 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002055{
Jiajia Qin5451d532017-11-16 17:16:34 +08002056 // TODO(Jiajia): Add image uniform check in future.
2057 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002058 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002059 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002060 return false;
2061 }
2062
Jiajia Qin5451d532017-11-16 17:16:34 +08002063 if (!program)
2064 {
2065 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2066 return false;
2067 }
2068
2069 if (!program->isLinked())
2070 {
2071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2072 return false;
2073 }
2074
2075 if (location == -1)
2076 {
2077 // Silently ignore the uniform command
2078 return false;
2079 }
2080
2081 const auto &uniformLocations = program->getUniformLocations();
2082 size_t castedLocation = static_cast<size_t>(location);
2083 if (castedLocation >= uniformLocations.size())
2084 {
2085 context->handleError(InvalidOperation() << "Invalid uniform location");
2086 return false;
2087 }
2088
2089 const auto &uniformLocation = uniformLocations[castedLocation];
2090 if (uniformLocation.ignored)
2091 {
2092 // Silently ignore the uniform command
2093 return false;
2094 }
2095
2096 if (!uniformLocation.used())
2097 {
2098 context->handleError(InvalidOperation());
2099 return false;
2100 }
2101
2102 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2103
2104 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002105 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002106 {
2107 context->handleError(InvalidOperation());
2108 return false;
2109 }
2110
2111 *uniformOut = &uniform;
2112 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002113}
2114
Jamie Madill5b772312018-03-08 20:28:32 -05002115bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002116 GLenum uniformType,
2117 GLsizei count,
2118 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002119{
Jiajia Qin5451d532017-11-16 17:16:34 +08002120 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2121 // It is compatible with INT or BOOL.
2122 // Do these cheap tests first, for a little extra speed.
2123 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002124 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002125 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002126 }
2127
Jiajia Qin5451d532017-11-16 17:16:34 +08002128 if (IsSamplerType(uniformType))
2129 {
2130 // Check that the values are in range.
2131 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2132 for (GLsizei i = 0; i < count; ++i)
2133 {
2134 if (value[i] < 0 || value[i] >= max)
2135 {
2136 context->handleError(InvalidValue() << "sampler uniform value out of range");
2137 return false;
2138 }
2139 }
2140 return true;
2141 }
2142
2143 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2144 return false;
2145}
2146
Jamie Madill5b772312018-03-08 20:28:32 -05002147bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002148{
2149 // Check that the value type is compatible with uniform type.
2150 // Do the cheaper test first, for a little extra speed.
2151 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2152 {
2153 return true;
2154 }
2155
2156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2157 return false;
2158}
2159
Jamie Madill5b772312018-03-08 20:28:32 -05002160bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002161{
2162 // Check that the value type is compatible with uniform type.
2163 if (valueType == uniformType)
2164 {
2165 return true;
2166 }
2167
2168 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2169 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002170}
2171
Jamie Madill5b772312018-03-08 20:28:32 -05002172bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002173{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002174 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002175 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002176 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2177 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002178}
2179
Jamie Madill5b772312018-03-08 20:28:32 -05002180bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002181{
2182 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002183 Program *programObject = context->getGLState().getProgram();
Frank Henigmana98a6472017-02-02 21:38:32 -05002184 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2185 ValidateUniform1ivValue(context, uniform->type, count, value);
2186}
2187
Jamie Madill5b772312018-03-08 20:28:32 -05002188bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002189 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002190 GLint location,
2191 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002192 GLboolean transpose)
2193{
Geoff Lang92019432017-11-20 13:09:34 -05002194 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002196 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002197 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002198 }
2199
Jamie Madill62d31cb2015-09-11 13:25:51 -04002200 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002201 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002202 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2203 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002204}
2205
Jamie Madill5b772312018-03-08 20:28:32 -05002206bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002207{
2208 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002210 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002211 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002212 }
2213
Jamie Madill0af26e12015-03-05 19:54:33 -05002214 const Caps &caps = context->getCaps();
2215
Jamie Madill893ab082014-05-16 16:56:10 -04002216 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2217 {
2218 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2219
Jamie Madill0af26e12015-03-05 19:54:33 -05002220 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002222 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002223 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002224 }
2225 }
2226
2227 switch (pname)
2228 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002229 case GL_TEXTURE_BINDING_2D:
2230 case GL_TEXTURE_BINDING_CUBE_MAP:
2231 case GL_TEXTURE_BINDING_3D:
2232 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002233 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002234 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002235 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2236 if (!context->getExtensions().textureRectangle)
2237 {
2238 context->handleError(InvalidEnum()
2239 << "ANGLE_texture_rectangle extension not present");
2240 return false;
2241 }
2242 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002243 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2244 if (!context->getExtensions().eglStreamConsumerExternal &&
2245 !context->getExtensions().eglImageExternal)
2246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002247 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2248 "nor GL_OES_EGL_image_external "
2249 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002250 return false;
2251 }
2252 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002253
He Yunchaoced53ae2016-11-29 15:00:51 +08002254 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2255 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002256 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002257 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2258 ASSERT(readFramebuffer);
2259
Jamie Madill427064d2018-04-13 16:20:34 -04002260 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002261 {
Geoff Langb1196682014-07-23 13:47:29 -04002262 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002263 }
2264
Jamie Madille98b1b52018-03-08 09:47:23 -05002265 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002266 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002268 return false;
2269 }
2270
Jamie Madille98b1b52018-03-08 09:47:23 -05002271 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002272 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002274 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002275 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002276 }
2277 }
2278 break;
2279
He Yunchaoced53ae2016-11-29 15:00:51 +08002280 default:
2281 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002282 }
2283
2284 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002285 if (*numParams == 0)
2286 {
2287 return false;
2288 }
2289
2290 return true;
2291}
2292
Brandon Jonesd1049182018-03-28 10:02:20 -07002293bool ValidateGetBooleanvRobustANGLE(Context *context,
2294 GLenum pname,
2295 GLsizei bufSize,
2296 GLsizei *length,
2297 GLboolean *params)
2298{
2299 GLenum nativeType;
2300 unsigned int numParams = 0;
2301
2302 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2303 {
2304 return false;
2305 }
2306
2307 SetRobustLengthParam(length, numParams);
2308
2309 return true;
2310}
2311
2312bool ValidateGetFloatvRobustANGLE(Context *context,
2313 GLenum pname,
2314 GLsizei bufSize,
2315 GLsizei *length,
2316 GLfloat *params)
2317{
2318 GLenum nativeType;
2319 unsigned int numParams = 0;
2320
2321 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2322 {
2323 return false;
2324 }
2325
2326 SetRobustLengthParam(length, numParams);
2327
2328 return true;
2329}
2330
2331bool ValidateGetIntegervRobustANGLE(Context *context,
2332 GLenum pname,
2333 GLsizei bufSize,
2334 GLsizei *length,
2335 GLint *data)
2336{
2337 GLenum nativeType;
2338 unsigned int numParams = 0;
2339
2340 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2341 {
2342 return false;
2343 }
2344
2345 SetRobustLengthParam(length, numParams);
2346
2347 return true;
2348}
2349
2350bool ValidateGetInteger64vRobustANGLE(Context *context,
2351 GLenum pname,
2352 GLsizei bufSize,
2353 GLsizei *length,
2354 GLint64 *data)
2355{
2356 GLenum nativeType;
2357 unsigned int numParams = 0;
2358
2359 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2360 {
2361 return false;
2362 }
2363
2364 if (nativeType == GL_INT_64_ANGLEX)
2365 {
2366 CastStateValues(context, nativeType, pname, numParams, data);
2367 return false;
2368 }
2369
2370 SetRobustLengthParam(length, numParams);
2371 return true;
2372}
2373
Jamie Madill5b772312018-03-08 20:28:32 -05002374bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002375 GLenum pname,
2376 GLsizei bufSize,
2377 GLenum *nativeType,
2378 unsigned int *numParams)
2379{
2380 if (!ValidateRobustEntryPoint(context, bufSize))
2381 {
2382 return false;
2383 }
2384
2385 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2386 {
2387 return false;
2388 }
2389
2390 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002391 {
2392 return false;
2393 }
2394
2395 return true;
2396}
2397
Jamie Madill5b772312018-03-08 20:28:32 -05002398bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002399 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002400 GLint level,
2401 GLenum internalformat,
2402 bool isSubImage,
2403 GLint xoffset,
2404 GLint yoffset,
2405 GLint zoffset,
2406 GLint x,
2407 GLint y,
2408 GLsizei width,
2409 GLsizei height,
2410 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002411 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002412{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002413 TextureType texType = TextureTargetToType(target);
2414
Brandon Jones6cad5662017-06-14 13:25:13 -07002415 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002416 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002417 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2418 return false;
2419 }
2420
2421 if (width < 0 || height < 0)
2422 {
2423 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002424 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002425 }
2426
He Yunchaoced53ae2016-11-29 15:00:51 +08002427 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2428 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002430 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002431 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002432 }
2433
2434 if (border != 0)
2435 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002436 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002437 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002438 }
2439
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002440 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002441 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002442 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002443 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002444 }
2445
Jamie Madill43da7c42018-08-01 11:34:49 -04002446 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002447 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002448 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002449 {
Geoff Langb1196682014-07-23 13:47:29 -04002450 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002451 }
2452
Jamie Madille98b1b52018-03-08 09:47:23 -05002453 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002454 {
Geoff Langb1196682014-07-23 13:47:29 -04002455 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002456 }
2457
Martin Radev138064f2016-07-15 12:03:41 +03002458 if (readFramebuffer->getReadBufferState() == GL_NONE)
2459 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002460 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002461 return false;
2462 }
2463
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002464 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2465 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002466 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002467 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002468 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2469 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002472 return false;
2473 }
2474
Martin Radev04e2c3b2017-07-27 16:54:35 +03002475 // ANGLE_multiview spec, Revision 1:
2476 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2477 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002478 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2479 // framebuffer is more than one.
2480 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002481 {
2482 context->handleError(InvalidFramebufferOperation()
2483 << "The active read framebuffer object has multiview attachments.");
2484 return false;
2485 }
2486
Jamie Madill43da7c42018-08-01 11:34:49 -04002487 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002488
Geoff Langaae65a42014-05-26 12:43:44 -04002489 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002490 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002491 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002492 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002493 maxDimension = caps.max2DTextureSize;
2494 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002495
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002496 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002497 maxDimension = caps.maxCubeMapTextureSize;
2498 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002499
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002500 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002501 maxDimension = caps.maxRectangleTextureSize;
2502 break;
2503
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002504 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 maxDimension = caps.max2DTextureSize;
2506 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002507
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002508 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002509 maxDimension = caps.max3DTextureSize;
2510 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002511
He Yunchaoced53ae2016-11-29 15:00:51 +08002512 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002513 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002514 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002515 }
2516
Jamie Madill43da7c42018-08-01 11:34:49 -04002517 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002518 if (!texture)
2519 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002520 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002521 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002522 }
2523
Geoff Lang69cce582015-09-17 13:20:36 -04002524 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002526 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002527 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002528 }
2529
Jamie Madill43da7c42018-08-01 11:34:49 -04002530 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002531 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002532 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002533
Geoff Lang966c9402017-04-18 12:38:27 -04002534 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002536 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002537 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002538 }
2539
2540 if (isSubImage)
2541 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002542 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2543 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2544 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002546 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002547 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002548 }
2549 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002550 else
2551 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002552 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002553 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002554 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002555 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002556 }
2557
Geoff Langeb66a6e2016-10-31 13:06:12 -04002558 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002559 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002560 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002561 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002562 }
2563
2564 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002565 if (static_cast<int>(width) > maxLevelDimension ||
2566 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002567 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002568 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002569 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002570 }
2571 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002572
Jamie Madill0c8abca2016-07-22 20:21:26 -04002573 if (textureFormatOut)
2574 {
2575 *textureFormatOut = texture->getFormat(target, level);
2576 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002577
2578 // Detect texture copying feedback loops for WebGL.
2579 if (context->getExtensions().webglCompatibility)
2580 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002581 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002582 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002583 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002584 return false;
2585 }
2586 }
2587
Jamie Madill560a8d82014-05-21 13:06:20 -04002588 return true;
2589}
2590
Jamie Madill493f9572018-05-24 19:52:15 -04002591bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002592{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002593 const Extensions &extensions = context->getExtensions();
2594
Jamie Madill1aeb1312014-06-20 13:21:25 -04002595 switch (mode)
2596 {
Jamie Madill493f9572018-05-24 19:52:15 -04002597 case PrimitiveMode::Points:
2598 case PrimitiveMode::Lines:
2599 case PrimitiveMode::LineLoop:
2600 case PrimitiveMode::LineStrip:
2601 case PrimitiveMode::Triangles:
2602 case PrimitiveMode::TriangleStrip:
2603 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002604 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002605
Jamie Madill493f9572018-05-24 19:52:15 -04002606 case PrimitiveMode::LinesAdjacency:
2607 case PrimitiveMode::LineStripAdjacency:
2608 case PrimitiveMode::TrianglesAdjacency:
2609 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002610 if (!extensions.geometryShader)
2611 {
2612 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2613 return false;
2614 }
2615 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002616 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002617 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002618 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002619 }
2620
Jamie Madill250d33f2014-06-06 17:09:03 -04002621 if (count < 0)
2622 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002623 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002624 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002625 }
2626
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002627 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002628
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002629 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2630 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2631 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madillcc73f242018-08-01 11:34:48 -04002632 if (!extensions.webglCompatibility && state.getVertexArray()->hasMappedEnabledArrayBuffer())
Jamie Madill250d33f2014-06-06 17:09:03 -04002633 {
Jamie Madillcc73f242018-08-01 11:34:48 -04002634 context->handleError(InvalidOperation());
2635 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002636 }
2637
Jamie Madillcbcde722017-01-06 14:50:00 -05002638 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2639 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002640 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002641 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002642 {
Ken Russellb9f92502018-01-27 19:00:26 -08002643 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002644 const FramebufferAttachment *dsAttachment =
2645 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002646 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2647 ASSERT(stencilBits <= 8);
2648
Jinyoung Hur85769f02015-10-20 17:08:44 -04002649 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002650 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002651 {
Ken Russellb9f92502018-01-27 19:00:26 -08002652 GLuint maxStencilValue = (1 << stencilBits) - 1;
2653
2654 bool differentRefs =
2655 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2656 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2657 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2658 (depthStencilState.stencilBackWritemask & maxStencilValue);
2659 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2660 (depthStencilState.stencilBackMask & maxStencilValue);
2661
2662 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002663 {
Ken Russellb9f92502018-01-27 19:00:26 -08002664 if (!extensions.webglCompatibility)
2665 {
Jamie Madilla2f043d2018-07-10 17:21:20 -04002666 WARN() << "This ANGLE implementation does not support separate front/back "
2667 "stencil writemasks, reference values, or stencil mask values.";
Ken Russellb9f92502018-01-27 19:00:26 -08002668 }
2669 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2670 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002671 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002672 }
Jamie Madillac528012014-06-20 13:21:23 -04002673 }
2674
Jamie Madill427064d2018-04-13 16:20:34 -04002675 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002676 {
Geoff Langb1196682014-07-23 13:47:29 -04002677 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002678 }
2679
Jamie Madill2da53562018-08-01 11:34:47 -04002680 if (context->getStateCache().hasAnyEnabledClientAttrib())
2681 {
2682 if (!ValidateDrawClientAttribs(context))
2683 {
2684 return false;
2685 }
2686 }
2687
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002688 // If we are running GLES1, there is no current program.
2689 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002690 {
Jamie Madill43da7c42018-08-01 11:34:49 -04002691 Program *program = state.getProgram();
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002692 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002693 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002694 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002695 return false;
2696 }
Martin Radev7e69f762017-07-27 14:54:13 +03002697
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002698 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2699 // vertex shader stage or fragment shader stage is a undefined behaviour.
2700 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2701 // produce undefined result.
2702 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2703 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002704 {
2705 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002706 << "It is a undefined behaviour to render without "
2707 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002708 return false;
2709 }
Martin Radevffe754b2017-07-31 10:38:07 +03002710
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002711 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002712 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002713 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002714 return false;
2715 }
2716
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002717 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002718 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002719 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2720 const int framebufferNumViews = framebuffer->getNumViews();
2721 if (framebufferNumViews != programNumViews)
2722 {
2723 context->handleError(InvalidOperation()
2724 << "The number of views in the active program "
2725 "and draw framebuffer does not match.");
2726 return false;
2727 }
2728
2729 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2730 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2731 framebufferNumViews > 1)
2732 {
2733 context->handleError(InvalidOperation()
2734 << "There is an active transform feedback object "
2735 "when the number of views in the active draw "
2736 "framebuffer is greater than 1.");
2737 return false;
2738 }
2739
2740 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2741 state.isQueryActive(QueryType::TimeElapsed))
2742 {
2743 context->handleError(InvalidOperation()
2744 << "There is an active query for target "
2745 "GL_TIME_ELAPSED_EXT when the number of "
2746 "views in the active draw framebuffer is "
2747 "greater than 1.");
2748 return false;
2749 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002750 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002751
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002752 // Do geometry shader specific validations
2753 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002754 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002755 if (!IsCompatibleDrawModeWithGeometryShader(
2756 mode, program->getGeometryShaderInputPrimitiveType()))
2757 {
2758 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2759 IncompatibleDrawModeAgainstGeometryShader);
2760 return false;
2761 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002762 }
Geoff Lange0cff192017-05-30 13:04:56 -04002763
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002764 // Uniform buffer validation
2765 for (unsigned int uniformBlockIndex = 0;
2766 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002767 {
Jamie Madill43da7c42018-08-01 11:34:49 -04002768 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002769 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2770 const OffsetBindingPointer<Buffer> &uniformBuffer =
2771 state.getIndexedUniformBuffer(blockBinding);
2772
2773 if (uniformBuffer.get() == nullptr)
2774 {
2775 // undefined behaviour
2776 context->handleError(
2777 InvalidOperation()
2778 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2779 return false;
2780 }
2781
2782 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2783 if (uniformBufferSize < uniformBlock.dataSize)
2784 {
2785 // undefined behaviour
2786 context->handleError(
2787 InvalidOperation()
2788 << "It is undefined behaviour to use a uniform buffer that is too small.");
2789 return false;
2790 }
2791
2792 if (extensions.webglCompatibility &&
2793 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2794 {
2795 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2796 UniformBufferBoundForTransformFeedback);
2797 return false;
2798 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002799 }
2800
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002801 // Do some additonal WebGL-specific validation
2802 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002803 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002804 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2805 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2806 transformFeedbackObject->buffersBoundForOtherUse())
2807 {
2808 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2809 TransformFeedbackBufferDoubleBound);
2810 return false;
2811 }
2812 // Detect rendering feedback loops for WebGL.
2813 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2814 {
2815 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2816 return false;
2817 }
2818
2819 // Detect that the vertex shader input types match the attribute types
2820 if (!ValidateVertexShaderAttributeTypeMatch(context))
2821 {
2822 return false;
2823 }
2824
2825 // Detect that the color buffer types match the fragment shader output types
2826 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2827 {
2828 return false;
2829 }
Jamie Madillac43aaa2018-07-31 11:22:13 -04002830
2831 if (count > 0)
2832 {
2833 const VertexArray *vao = context->getGLState().getVertexArray();
2834 if (vao->hasTransformFeedbackBindingConflict(context))
2835 {
2836 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2837 VertexBufferBoundForTransformFeedback);
2838 return false;
2839 }
2840 }
Geoff Lange0cff192017-05-30 13:04:56 -04002841 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002842 }
2843
Jamie Madill9fdaa492018-02-16 10:52:11 -05002844 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002845}
2846
Jamie Madill5b772312018-03-08 20:28:32 -05002847bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002848 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002849 GLint first,
2850 GLsizei count,
2851 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002852{
Jamie Madillfd716582014-06-06 17:09:04 -04002853 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002854 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002855 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002856 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002857 }
2858
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002859 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04002860 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002861 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002862 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002863 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002864 if (!ValidateTransformFeedbackPrimitiveMode(context,
2865 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002866 {
James Darpinian30b604d2018-03-12 17:26:57 -07002867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2868 return false;
2869 }
2870
2871 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2872 {
2873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2874 return false;
2875 }
Jamie Madillfd716582014-06-06 17:09:04 -04002876 }
2877
Jiajia Qind9671222016-11-29 16:30:31 +08002878 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002879 {
2880 return false;
2881 }
2882
Corentin Wallez71168a02016-12-19 15:11:18 -08002883 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002884 // - first < 0 has been checked as an error condition.
2885 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002886 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002887 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002888 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002889 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002890 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2891 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2892 {
2893 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2894 return false;
2895 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002896
Jamie Madill2da53562018-08-01 11:34:47 -04002897 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002898 {
2899 return false;
2900 }
Jamie Madillfd716582014-06-06 17:09:04 -04002901 }
2902
2903 return true;
2904}
2905
He Yunchaoced53ae2016-11-29 15:00:51 +08002906bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002907 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002908 GLint first,
2909 GLsizei count,
2910 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002911{
Geoff Lang63c5a592017-09-27 14:08:16 -04002912 if (!context->getExtensions().instancedArrays)
2913 {
2914 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2915 return false;
2916 }
2917
Corentin Wallez170efbf2017-05-02 13:45:01 -04002918 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002919 {
2920 return false;
2921 }
2922
Corentin Wallez0dc97812017-06-22 14:38:44 -04002923 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002924}
2925
Jamie Madill493f9572018-05-24 19:52:15 -04002926bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002927{
Jamie Madill250d33f2014-06-06 17:09:03 -04002928 switch (type)
2929 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002930 case GL_UNSIGNED_BYTE:
2931 case GL_UNSIGNED_SHORT:
2932 break;
2933 case GL_UNSIGNED_INT:
2934 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2935 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002936 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002937 return false;
2938 }
2939 break;
2940 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002941 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002942 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002943 }
2944
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002945 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002946
Jamie Madill43da7c42018-08-01 11:34:49 -04002947 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002948 if (curTransformFeedback && curTransformFeedback->isActive() &&
2949 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002950 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002951 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2952 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2953 if (context->getExtensions().geometryShader)
2954 {
2955 if (!ValidateTransformFeedbackPrimitiveMode(
2956 context, curTransformFeedback->getPrimitiveMode(), mode))
2957 {
2958 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2959 return false;
2960 }
2961 }
2962 else
2963 {
2964 // It is an invalid operation to call DrawElements, DrawRangeElements or
2965 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2966 // 86)
2967 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2968 UnsupportedDrawModeForTransformFeedback);
2969 return false;
2970 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002971 }
2972
Jiajia Qind9671222016-11-29 16:30:31 +08002973 return true;
2974}
2975
Jamie Madill5b772312018-03-08 20:28:32 -05002976bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002977 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002978 GLsizei count,
2979 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002980 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002981 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002982{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002983 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08002984 return false;
2985
2986 const State &state = context->getGLState();
2987
Corentin Wallez170efbf2017-05-02 13:45:01 -04002988 if (!ValidateDrawBase(context, mode, count))
2989 {
2990 return false;
2991 }
2992
Jamie Madill43da7c42018-08-01 11:34:49 -04002993 const VertexArray *vao = state.getVertexArray();
2994 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002995
Jamie Madill43da7c42018-08-01 11:34:49 -04002996 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002997
2998 if (context->getExtensions().webglCompatibility)
2999 {
3000 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3001 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3002 {
3003 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3004 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3005 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003007 return false;
3008 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003009
3010 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3011 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3012 // error is generated.
3013 if (reinterpret_cast<intptr_t>(indices) < 0)
3014 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003015 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003016 return false;
3017 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003018 }
Jamie Madillcc73f242018-08-01 11:34:48 -04003019 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
3020 {
3021 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3022 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3023 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3024 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3025 return false;
3026 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003027
3028 if (context->getExtensions().webglCompatibility ||
3029 !context->getGLState().areClientArraysEnabled())
3030 {
Brandon Jones2a018152018-06-08 15:59:26 -07003031 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003032 {
3033 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003034 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3035 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003036 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003037 return false;
3038 }
3039 }
3040
Jamie Madill9fdaa492018-02-16 10:52:11 -05003041 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003042 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003043 // This is an application error that would normally result in a crash, but we catch it and
3044 // return an error
3045 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3046 return false;
3047 }
3048
3049 if (count > 0 && elementArrayBuffer)
3050 {
3051 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3052 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3053 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3054 constexpr uint64_t kMaxTypeSize = 8;
3055 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3056 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3057 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3058
3059 uint64_t typeSize = typeBytes;
3060 uint64_t elementCount = static_cast<uint64_t>(count);
3061 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3062
3063 // Doing the multiplication here is overflow-safe
3064 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3065
3066 // The offset can be any value, check for overflows
3067 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3068 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003069 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3071 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003072 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003073
3074 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3075 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003076 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003077 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3078 return false;
3079 }
3080
3081 ASSERT(isPow2(typeSize) && typeSize > 0);
3082 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3083 {
3084 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003085 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003086 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003087
3088 if (context->getExtensions().webglCompatibility &&
3089 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3090 {
3091 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3092 ElementArrayBufferBoundForTransformFeedback);
3093 return false;
3094 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003095 }
3096
Jamie Madill2da53562018-08-01 11:34:47 -04003097 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003098 {
3099 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003100 const DrawCallParams &params = context->getParams<DrawCallParams>();
3101 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3102 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003103
3104 // If we use an index greater than our maximum supported index range, return an error.
3105 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3106 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003107 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003108 {
3109 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3110 return false;
3111 }
3112
Jamie Madill2da53562018-08-01 11:34:47 -04003113 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003114 {
3115 return false;
3116 }
3117
3118 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003119 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003120 }
3121
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003122 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003123}
3124
Jamie Madill5b772312018-03-08 20:28:32 -05003125bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003126 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003127 GLsizei count,
3128 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003129 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003130 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003131{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003132 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003133}
3134
Geoff Lang3edfe032015-09-04 16:38:24 -04003135bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003136 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003137 GLsizei count,
3138 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003139 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003140 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003141{
Geoff Lang63c5a592017-09-27 14:08:16 -04003142 if (!context->getExtensions().instancedArrays)
3143 {
3144 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3145 return false;
3146 }
3147
Corentin Wallez170efbf2017-05-02 13:45:01 -04003148 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003149 {
3150 return false;
3151 }
3152
Corentin Wallez0dc97812017-06-22 14:38:44 -04003153 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003154}
3155
He Yunchaoced53ae2016-11-29 15:00:51 +08003156bool ValidateFramebufferTextureBase(Context *context,
3157 GLenum target,
3158 GLenum attachment,
3159 GLuint texture,
3160 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003161{
Geoff Lange8afa902017-09-27 15:00:43 -04003162 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003163 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003164 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003165 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003166 }
3167
3168 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003169 {
3170 return false;
3171 }
3172
Jamie Madill55ec3b12014-07-03 10:38:57 -04003173 if (texture != 0)
3174 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003175 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003176
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003177 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003179 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003180 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003181 }
3182
3183 if (level < 0)
3184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003185 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003186 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003187 }
3188 }
3189
Jamie Madill43da7c42018-08-01 11:34:49 -04003190 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003191 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003192
Jamie Madill84115c92015-04-23 15:00:07 -04003193 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003194 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003195 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003196 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003197 }
3198
3199 return true;
3200}
3201
Geoff Langb1196682014-07-23 13:47:29 -04003202bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003203{
3204 if (program == 0)
3205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003206 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003207 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003208 }
3209
Jamie Madill43da7c42018-08-01 11:34:49 -04003210 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003211 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003212 {
3213 return false;
3214 }
3215
Jamie Madill0063c512014-08-25 15:47:53 -04003216 if (!programObject || !programObject->isLinked())
3217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003219 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003220 }
3221
Geoff Lang7dd2e102014-11-10 15:19:26 -05003222 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003224 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003225 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003226 }
3227
Jamie Madill0063c512014-08-25 15:47:53 -04003228 return true;
3229}
3230
Geoff Langf41d0ee2016-10-07 13:04:23 -04003231static bool ValidateSizedGetUniform(Context *context,
3232 GLuint program,
3233 GLint location,
3234 GLsizei bufSize,
3235 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003236{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003237 if (length)
3238 {
3239 *length = 0;
3240 }
3241
Jamie Madill78f41802014-08-25 15:47:55 -04003242 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003243 {
Jamie Madill78f41802014-08-25 15:47:55 -04003244 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003245 }
3246
Geoff Langf41d0ee2016-10-07 13:04:23 -04003247 if (bufSize < 0)
3248 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003249 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003250 return false;
3251 }
3252
Jamie Madill43da7c42018-08-01 11:34:49 -04003253 Program *programObject = context->getProgram(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003254 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003255
Jamie Madill78f41802014-08-25 15:47:55 -04003256 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003257 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003258 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003259 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003260 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003261 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003262 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003263 }
3264
Geoff Langf41d0ee2016-10-07 13:04:23 -04003265 if (length)
3266 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003267 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003268 }
3269
Jamie Madill0063c512014-08-25 15:47:53 -04003270 return true;
3271}
3272
He Yunchaoced53ae2016-11-29 15:00:51 +08003273bool ValidateGetnUniformfvEXT(Context *context,
3274 GLuint program,
3275 GLint location,
3276 GLsizei bufSize,
3277 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003278{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003279 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003280}
3281
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003282bool ValidateGetnUniformfvRobustANGLE(Context *context,
3283 GLuint program,
3284 GLint location,
3285 GLsizei bufSize,
3286 GLsizei *length,
3287 GLfloat *params)
3288{
3289 UNIMPLEMENTED();
3290 return false;
3291}
3292
He Yunchaoced53ae2016-11-29 15:00:51 +08003293bool ValidateGetnUniformivEXT(Context *context,
3294 GLuint program,
3295 GLint location,
3296 GLsizei bufSize,
3297 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003298{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003299 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3300}
3301
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003302bool ValidateGetnUniformivRobustANGLE(Context *context,
3303 GLuint program,
3304 GLint location,
3305 GLsizei bufSize,
3306 GLsizei *length,
3307 GLint *params)
3308{
3309 UNIMPLEMENTED();
3310 return false;
3311}
3312
3313bool ValidateGetnUniformuivRobustANGLE(Context *context,
3314 GLuint program,
3315 GLint location,
3316 GLsizei bufSize,
3317 GLsizei *length,
3318 GLuint *params)
3319{
3320 UNIMPLEMENTED();
3321 return false;
3322}
3323
Geoff Langf41d0ee2016-10-07 13:04:23 -04003324bool ValidateGetUniformfvRobustANGLE(Context *context,
3325 GLuint program,
3326 GLint location,
3327 GLsizei bufSize,
3328 GLsizei *length,
3329 GLfloat *params)
3330{
3331 if (!ValidateRobustEntryPoint(context, bufSize))
3332 {
3333 return false;
3334 }
3335
Brandon Jonesd1049182018-03-28 10:02:20 -07003336 GLsizei writeLength = 0;
3337
Geoff Langf41d0ee2016-10-07 13:04:23 -04003338 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003339 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3340 {
3341 return false;
3342 }
3343
3344 SetRobustLengthParam(length, writeLength);
3345
3346 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003347}
3348
3349bool ValidateGetUniformivRobustANGLE(Context *context,
3350 GLuint program,
3351 GLint location,
3352 GLsizei bufSize,
3353 GLsizei *length,
3354 GLint *params)
3355{
3356 if (!ValidateRobustEntryPoint(context, bufSize))
3357 {
3358 return false;
3359 }
3360
Brandon Jonesd1049182018-03-28 10:02:20 -07003361 GLsizei writeLength = 0;
3362
Geoff Langf41d0ee2016-10-07 13:04:23 -04003363 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003364 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3365 {
3366 return false;
3367 }
3368
3369 SetRobustLengthParam(length, writeLength);
3370
3371 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003372}
3373
3374bool ValidateGetUniformuivRobustANGLE(Context *context,
3375 GLuint program,
3376 GLint location,
3377 GLsizei bufSize,
3378 GLsizei *length,
3379 GLuint *params)
3380{
3381 if (!ValidateRobustEntryPoint(context, bufSize))
3382 {
3383 return false;
3384 }
3385
3386 if (context->getClientMajorVersion() < 3)
3387 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003388 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003389 return false;
3390 }
3391
Brandon Jonesd1049182018-03-28 10:02:20 -07003392 GLsizei writeLength = 0;
3393
Geoff Langf41d0ee2016-10-07 13:04:23 -04003394 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003395 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3396 {
3397 return false;
3398 }
3399
3400 SetRobustLengthParam(length, writeLength);
3401
3402 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003403}
3404
He Yunchaoced53ae2016-11-29 15:00:51 +08003405bool ValidateDiscardFramebufferBase(Context *context,
3406 GLenum target,
3407 GLsizei numAttachments,
3408 const GLenum *attachments,
3409 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003410{
3411 if (numAttachments < 0)
3412 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003413 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003414 return false;
3415 }
3416
3417 for (GLsizei i = 0; i < numAttachments; ++i)
3418 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003419 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003420 {
3421 if (defaultFramebuffer)
3422 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003423 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003424 return false;
3425 }
3426
3427 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003429 context->handleError(InvalidOperation() << "Requested color attachment is "
3430 "greater than the maximum supported "
3431 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003432 return false;
3433 }
3434 }
3435 else
3436 {
3437 switch (attachments[i])
3438 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003439 case GL_DEPTH_ATTACHMENT:
3440 case GL_STENCIL_ATTACHMENT:
3441 case GL_DEPTH_STENCIL_ATTACHMENT:
3442 if (defaultFramebuffer)
3443 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003444 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3445 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003446 return false;
3447 }
3448 break;
3449 case GL_COLOR:
3450 case GL_DEPTH:
3451 case GL_STENCIL:
3452 if (!defaultFramebuffer)
3453 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003454 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3455 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003456 return false;
3457 }
3458 break;
3459 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003460 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003461 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003462 }
3463 }
3464 }
3465
3466 return true;
3467}
3468
Austin Kinross6ee1e782015-05-29 17:05:37 -07003469bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3470{
Jamie Madill007530e2017-12-28 14:27:04 -05003471 if (!context->getExtensions().debugMarker)
3472 {
3473 // The debug marker calls should not set error state
3474 // However, it seems reasonable to set an error state if the extension is not enabled
3475 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3476 return false;
3477 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003478
Jamie Madill007530e2017-12-28 14:27:04 -05003479 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003480 if (length < 0)
3481 {
3482 return false;
3483 }
3484
3485 if (marker == nullptr)
3486 {
3487 return false;
3488 }
3489
3490 return true;
3491}
3492
3493bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3494{
Jamie Madill007530e2017-12-28 14:27:04 -05003495 if (!context->getExtensions().debugMarker)
3496 {
3497 // The debug marker calls should not set error state
3498 // However, it seems reasonable to set an error state if the extension is not enabled
3499 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3500 return false;
3501 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003502
Jamie Madill007530e2017-12-28 14:27:04 -05003503 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003504 if (length < 0)
3505 {
3506 return false;
3507 }
3508
3509 if (length > 0 && marker == nullptr)
3510 {
3511 return false;
3512 }
3513
3514 return true;
3515}
3516
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003517bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003518{
Geoff Langa8406172015-07-21 16:53:39 -04003519 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003521 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003522 return false;
3523 }
3524
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003525 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003526 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003527 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003528 if (!context->getExtensions().eglImage)
3529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003530 context->handleError(InvalidEnum()
3531 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003532 }
3533 break;
3534
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003535 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003536 if (!context->getExtensions().eglImageExternal)
3537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003538 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3539 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003540 }
Geoff Langa8406172015-07-21 16:53:39 -04003541 break;
3542
3543 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003544 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003545 return false;
3546 }
3547
Rafael Cintron05a449a2018-06-20 18:08:04 -07003548 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003549
Jamie Madill61e16b42017-06-19 11:13:23 -04003550 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003551 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003553 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003554 return false;
3555 }
3556
Jamie Madill007530e2017-12-28 14:27:04 -05003557 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003559 context->handleError(InvalidOperation()
3560 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003561 return false;
3562 }
3563
Geoff Langca271392017-04-05 12:30:00 -04003564 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003565 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003566 if (!textureCaps.texturable)
3567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003568 context->handleError(InvalidOperation()
3569 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003570 return false;
3571 }
3572
Geoff Langdcab33b2015-07-21 13:03:16 -04003573 return true;
3574}
3575
3576bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003577 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003578 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003579{
Geoff Langa8406172015-07-21 16:53:39 -04003580 if (!context->getExtensions().eglImage)
3581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003582 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003583 return false;
3584 }
3585
3586 switch (target)
3587 {
3588 case GL_RENDERBUFFER:
3589 break;
3590
3591 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003592 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003593 return false;
3594 }
3595
Rafael Cintron05a449a2018-06-20 18:08:04 -07003596 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003597
Jamie Madill61e16b42017-06-19 11:13:23 -04003598 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003599 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003601 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003602 return false;
3603 }
3604
Geoff Langca271392017-04-05 12:30:00 -04003605 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003606 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003607 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003609 context->handleError(InvalidOperation()
3610 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003611 return false;
3612 }
3613
Geoff Langdcab33b2015-07-21 13:03:16 -04003614 return true;
3615}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003616
3617bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3618{
Geoff Lang36167ab2015-12-07 10:27:14 -05003619 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003620 {
3621 // The default VAO should always exist
3622 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003623 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003624 return false;
3625 }
3626
3627 return true;
3628}
3629
Geoff Langc5629752015-12-07 16:29:04 -05003630bool ValidateProgramBinaryBase(Context *context,
3631 GLuint program,
3632 GLenum binaryFormat,
3633 const void *binary,
3634 GLint length)
3635{
3636 Program *programObject = GetValidProgram(context, program);
3637 if (programObject == nullptr)
3638 {
3639 return false;
3640 }
3641
3642 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3643 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3644 programBinaryFormats.end())
3645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003647 return false;
3648 }
3649
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003650 if (context->hasActiveTransformFeedback(program))
3651 {
3652 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003653 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3654 "is associated with an active transform "
3655 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003656 return false;
3657 }
3658
Geoff Langc5629752015-12-07 16:29:04 -05003659 return true;
3660}
3661
3662bool ValidateGetProgramBinaryBase(Context *context,
3663 GLuint program,
3664 GLsizei bufSize,
3665 GLsizei *length,
3666 GLenum *binaryFormat,
3667 void *binary)
3668{
3669 Program *programObject = GetValidProgram(context, program);
3670 if (programObject == nullptr)
3671 {
3672 return false;
3673 }
3674
3675 if (!programObject->isLinked())
3676 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003677 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003678 return false;
3679 }
3680
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003681 if (context->getCaps().programBinaryFormats.empty())
3682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003683 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003684 return false;
3685 }
3686
Geoff Langc5629752015-12-07 16:29:04 -05003687 return true;
3688}
Jamie Madillc29968b2016-01-20 11:17:23 -05003689
Jamie Madill5b772312018-03-08 20:28:32 -05003690bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003691{
3692 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003693 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003694 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003695 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3696 return false;
3697 }
3698 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3699 {
3700 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003701 return false;
3702 }
3703
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003704 ASSERT(context->getGLState().getDrawFramebuffer());
3705 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003706 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3707
3708 // This should come first before the check for the default frame buffer
3709 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3710 // rather than INVALID_OPERATION
3711 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3712 {
3713 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3714
3715 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003716 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3717 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003718 {
3719 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003720 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3721 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3722 // 3.1 is still a bit ambiguous about the error, but future specs are
3723 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003724 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003725 return false;
3726 }
3727 else if (bufs[colorAttachment] >= maxColorAttachment)
3728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003729 context->handleError(InvalidOperation()
3730 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003731 return false;
3732 }
3733 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3734 frameBufferId != 0)
3735 {
3736 // INVALID_OPERATION-GL is bound to buffer and ith argument
3737 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003738 context->handleError(InvalidOperation()
3739 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003740 return false;
3741 }
3742 }
3743
3744 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3745 // and n is not 1 or bufs is bound to value other than BACK and NONE
3746 if (frameBufferId == 0)
3747 {
3748 if (n != 1)
3749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003750 context->handleError(InvalidOperation()
3751 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003752 return false;
3753 }
3754
3755 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003757 context->handleError(
3758 InvalidOperation()
3759 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003760 return false;
3761 }
3762 }
3763
3764 return true;
3765}
3766
Geoff Lang496c02d2016-10-20 11:38:11 -07003767bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003768 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003769 GLenum pname,
3770 GLsizei *length,
3771 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003772{
Geoff Lang496c02d2016-10-20 11:38:11 -07003773 if (length)
3774 {
3775 *length = 0;
3776 }
3777
3778 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3779 {
3780 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003781 InvalidOperation()
3782 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003783 return false;
3784 }
3785
Corentin Walleze4477002017-12-01 14:39:58 -05003786 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003787 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003788 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003789 return false;
3790 }
3791
Geoff Lang496c02d2016-10-20 11:38:11 -07003792 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003793 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003794 case GL_BUFFER_MAP_POINTER:
3795 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003796
Geoff Lang496c02d2016-10-20 11:38:11 -07003797 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003798 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003799 return false;
3800 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003801
3802 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3803 // target bound to zero generate an INVALID_OPERATION error."
3804 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003805 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003806 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003807 context->handleError(InvalidOperation()
3808 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003809 return false;
3810 }
3811
Geoff Lang496c02d2016-10-20 11:38:11 -07003812 if (length)
3813 {
3814 *length = 1;
3815 }
3816
Olli Etuaho4f667482016-03-30 15:56:35 +03003817 return true;
3818}
3819
Corentin Wallez336129f2017-10-17 15:55:40 -04003820bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003821{
Corentin Walleze4477002017-12-01 14:39:58 -05003822 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003823 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003825 return false;
3826 }
3827
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003828 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003829
3830 if (buffer == nullptr || !buffer->isMapped())
3831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003832 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003833 return false;
3834 }
3835
3836 return true;
3837}
3838
3839bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003840 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003841 GLintptr offset,
3842 GLsizeiptr length,
3843 GLbitfield access)
3844{
Corentin Walleze4477002017-12-01 14:39:58 -05003845 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003847 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003848 return false;
3849 }
3850
Brandon Jones6cad5662017-06-14 13:25:13 -07003851 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003853 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3854 return false;
3855 }
3856
3857 if (length < 0)
3858 {
3859 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003860 return false;
3861 }
3862
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003863 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003864
3865 if (!buffer)
3866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003867 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003868 return false;
3869 }
3870
3871 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003872 CheckedNumeric<size_t> checkedOffset(offset);
3873 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003874
Jamie Madille2e406c2016-06-02 13:04:10 -04003875 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003877 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003878 return false;
3879 }
3880
3881 // Check for invalid bits in the mask
3882 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3883 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3884 GL_MAP_UNSYNCHRONIZED_BIT;
3885
3886 if (access & ~(allAccessBits))
3887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003888 context->handleError(InvalidValue()
3889 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003890 return false;
3891 }
3892
3893 if (length == 0)
3894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003895 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003896 return false;
3897 }
3898
3899 if (buffer->isMapped())
3900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003901 context->handleError(InvalidOperation() << "Buffer is already mapped.");
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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003908 context->handleError(InvalidOperation()
3909 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003910 return false;
3911 }
3912
3913 GLbitfield writeOnlyBits =
3914 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3915
3916 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003918 context->handleError(InvalidOperation()
3919 << "Invalid access bits when mapping buffer for reading: 0x"
3920 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003921 return false;
3922 }
3923
3924 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3925 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003926 context->handleError(
3927 InvalidOperation()
3928 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003929 return false;
3930 }
Geoff Lang79f71042017-08-14 16:43:43 -04003931
3932 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003933}
3934
3935bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003936 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003937 GLintptr offset,
3938 GLsizeiptr length)
3939{
Brandon Jones6cad5662017-06-14 13:25:13 -07003940 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003942 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3943 return false;
3944 }
3945
3946 if (length < 0)
3947 {
3948 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003949 return false;
3950 }
3951
Corentin Walleze4477002017-12-01 14:39:58 -05003952 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003953 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003954 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003955 return false;
3956 }
3957
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003958 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003959
3960 if (buffer == nullptr)
3961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003962 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003963 return false;
3964 }
3965
3966 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003968 context->handleError(InvalidOperation()
3969 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003970 return false;
3971 }
3972
3973 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003974 CheckedNumeric<size_t> checkedOffset(offset);
3975 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003976
Jamie Madille2e406c2016-06-02 13:04:10 -04003977 if (!checkedSize.IsValid() ||
3978 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003980 context->handleError(InvalidValue()
3981 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003982 return false;
3983 }
3984
3985 return true;
3986}
3987
Olli Etuaho41997e72016-03-10 13:38:39 +02003988bool ValidateGenOrDelete(Context *context, GLint n)
3989{
3990 if (n < 0)
3991 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003992 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003993 return false;
3994 }
3995 return true;
3996}
3997
Jamie Madill5b772312018-03-08 20:28:32 -05003998bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003999{
4000 if (!context->getExtensions().robustClientMemory)
4001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004002 context->handleError(InvalidOperation()
4003 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004004 return false;
4005 }
4006
4007 if (bufSize < 0)
4008 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004009 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004010 return false;
4011 }
4012
4013 return true;
4014}
4015
Jamie Madill5b772312018-03-08 20:28:32 -05004016bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004017{
4018 if (bufSize < numParams)
4019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004020 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4021 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004022 return false;
4023 }
4024
4025 return true;
4026}
4027
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004028bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004029 GLenum target,
4030 GLenum attachment,
4031 GLenum pname,
4032 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004033{
Geoff Lange8afa902017-09-27 15:00:43 -04004034 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004036 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004037 return false;
4038 }
4039
4040 int clientVersion = context->getClientMajorVersion();
4041
4042 switch (pname)
4043 {
4044 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4045 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4046 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4047 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4048 break;
4049
Martin Radeve5285d22017-07-14 16:23:53 +03004050 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4051 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4052 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4053 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4054 if (clientVersion < 3 || !context->getExtensions().multiview)
4055 {
4056 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4057 return false;
4058 }
4059 break;
4060
Geoff Langff5b2d52016-09-07 11:32:23 -04004061 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4062 if (clientVersion < 3 && !context->getExtensions().sRGB)
4063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004064 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004065 return false;
4066 }
4067 break;
4068
4069 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4070 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4071 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4072 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4073 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4074 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4075 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4076 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4077 if (clientVersion < 3)
4078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004079 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004080 return false;
4081 }
4082 break;
4083
Jiawei Shaoa8802472018-05-28 11:17:47 +08004084 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4085 if (!context->getExtensions().geometryShader)
4086 {
4087 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4088 return false;
4089 }
4090 break;
4091
Geoff Langff5b2d52016-09-07 11:32:23 -04004092 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004093 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004094 return false;
4095 }
4096
4097 // Determine if the attachment is a valid enum
4098 switch (attachment)
4099 {
4100 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004101 case GL_DEPTH:
4102 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004103 if (clientVersion < 3)
4104 {
Geoff Langfa125c92017-10-24 13:01:46 -04004105 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004106 return false;
4107 }
4108 break;
4109
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004110 case GL_DEPTH_STENCIL_ATTACHMENT:
4111 if (clientVersion < 3 && !context->isWebGL1())
4112 {
4113 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4114 return false;
4115 }
4116 break;
4117
Geoff Langfa125c92017-10-24 13:01:46 -04004118 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004119 case GL_DEPTH_ATTACHMENT:
4120 case GL_STENCIL_ATTACHMENT:
4121 break;
4122
4123 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004124 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4125 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004126 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4127 {
Geoff Langfa125c92017-10-24 13:01:46 -04004128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004129 return false;
4130 }
4131 break;
4132 }
4133
4134 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4135 ASSERT(framebuffer);
4136
4137 if (framebuffer->id() == 0)
4138 {
4139 if (clientVersion < 3)
4140 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004142 return false;
4143 }
4144
4145 switch (attachment)
4146 {
4147 case GL_BACK:
4148 case GL_DEPTH:
4149 case GL_STENCIL:
4150 break;
4151
4152 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004154 return false;
4155 }
4156 }
4157 else
4158 {
4159 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4160 {
4161 // Valid attachment query
4162 }
4163 else
4164 {
4165 switch (attachment)
4166 {
4167 case GL_DEPTH_ATTACHMENT:
4168 case GL_STENCIL_ATTACHMENT:
4169 break;
4170
4171 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004172 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004174 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004175 return false;
4176 }
4177 break;
4178
4179 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004181 return false;
4182 }
4183 }
4184 }
4185
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004186 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004187 if (attachmentObject)
4188 {
4189 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4190 attachmentObject->type() == GL_TEXTURE ||
4191 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4192
4193 switch (pname)
4194 {
4195 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4196 if (attachmentObject->type() != GL_RENDERBUFFER &&
4197 attachmentObject->type() != GL_TEXTURE)
4198 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004199 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004200 return false;
4201 }
4202 break;
4203
4204 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4205 if (attachmentObject->type() != GL_TEXTURE)
4206 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004207 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004208 return false;
4209 }
4210 break;
4211
4212 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4213 if (attachmentObject->type() != GL_TEXTURE)
4214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004215 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004216 return false;
4217 }
4218 break;
4219
4220 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4221 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4222 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004223 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004224 return false;
4225 }
4226 break;
4227
4228 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4229 if (attachmentObject->type() != GL_TEXTURE)
4230 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004231 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004232 return false;
4233 }
4234 break;
4235
4236 default:
4237 break;
4238 }
4239 }
4240 else
4241 {
4242 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4243 // is NONE, then querying any other pname will generate INVALID_ENUM.
4244
4245 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4246 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4247 // INVALID_OPERATION for all other pnames
4248
4249 switch (pname)
4250 {
4251 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4252 break;
4253
4254 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4255 if (clientVersion < 3)
4256 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004257 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004258 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004259 return false;
4260 }
4261 break;
4262
4263 default:
4264 if (clientVersion < 3)
4265 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004266 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004267 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004268 return false;
4269 }
4270 else
4271 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004272 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004273 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004274 return false;
4275 }
4276 }
4277 }
4278
Martin Radeve5285d22017-07-14 16:23:53 +03004279 if (numParams)
4280 {
4281 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4282 {
4283 // Only when the viewport offsets are queried we can have a varying number of output
4284 // parameters.
4285 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4286 *numParams = numViews * 2;
4287 }
4288 else
4289 {
4290 // For all other queries we can have only one output parameter.
4291 *numParams = 1;
4292 }
4293 }
4294
Geoff Langff5b2d52016-09-07 11:32:23 -04004295 return true;
4296}
4297
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004298bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004299 GLenum target,
4300 GLenum attachment,
4301 GLenum pname,
4302 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004303 GLsizei *length,
4304 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004305{
4306 if (!ValidateRobustEntryPoint(context, bufSize))
4307 {
4308 return false;
4309 }
4310
Brandon Jonesd1049182018-03-28 10:02:20 -07004311 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004312 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004313 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004314 {
4315 return false;
4316 }
4317
Brandon Jonesd1049182018-03-28 10:02:20 -07004318 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004319 {
4320 return false;
4321 }
4322
Brandon Jonesd1049182018-03-28 10:02:20 -07004323 SetRobustLengthParam(length, numParams);
4324
Geoff Langff5b2d52016-09-07 11:32:23 -04004325 return true;
4326}
4327
Jamie Madill5b772312018-03-08 20:28:32 -05004328bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004329 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004330 GLenum pname,
4331 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004332 GLsizei *length,
4333 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004334{
4335 if (!ValidateRobustEntryPoint(context, bufSize))
4336 {
4337 return false;
4338 }
4339
Brandon Jonesd1049182018-03-28 10:02:20 -07004340 GLsizei numParams = 0;
4341
4342 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004343 {
4344 return false;
4345 }
4346
Brandon Jonesd1049182018-03-28 10:02:20 -07004347 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004348 {
4349 return false;
4350 }
4351
Brandon Jonesd1049182018-03-28 10:02:20 -07004352 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004353 return true;
4354}
4355
Jamie Madill5b772312018-03-08 20:28:32 -05004356bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004357 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004358 GLenum pname,
4359 GLsizei bufSize,
4360 GLsizei *length,
4361 GLint64 *params)
4362{
Brandon Jonesd1049182018-03-28 10:02:20 -07004363 GLsizei numParams = 0;
4364
Geoff Langebebe1c2016-10-14 12:01:31 -04004365 if (!ValidateRobustEntryPoint(context, bufSize))
4366 {
4367 return false;
4368 }
4369
Brandon Jonesd1049182018-03-28 10:02:20 -07004370 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004371 {
4372 return false;
4373 }
4374
Brandon Jonesd1049182018-03-28 10:02:20 -07004375 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004376 {
4377 return false;
4378 }
4379
Brandon Jonesd1049182018-03-28 10:02:20 -07004380 SetRobustLengthParam(length, numParams);
4381
Geoff Langff5b2d52016-09-07 11:32:23 -04004382 return true;
4383}
4384
Jamie Madill5b772312018-03-08 20:28:32 -05004385bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004386{
4387 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004388 if (numParams)
4389 {
4390 *numParams = 1;
4391 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004392
4393 Program *programObject = GetValidProgram(context, program);
4394 if (!programObject)
4395 {
4396 return false;
4397 }
4398
4399 switch (pname)
4400 {
4401 case GL_DELETE_STATUS:
4402 case GL_LINK_STATUS:
4403 case GL_VALIDATE_STATUS:
4404 case GL_INFO_LOG_LENGTH:
4405 case GL_ATTACHED_SHADERS:
4406 case GL_ACTIVE_ATTRIBUTES:
4407 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4408 case GL_ACTIVE_UNIFORMS:
4409 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4410 break;
4411
4412 case GL_PROGRAM_BINARY_LENGTH:
4413 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004415 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4416 "requires GL_OES_get_program_binary or "
4417 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004418 return false;
4419 }
4420 break;
4421
4422 case GL_ACTIVE_UNIFORM_BLOCKS:
4423 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4424 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4425 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4426 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4427 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4428 if (context->getClientMajorVersion() < 3)
4429 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004430 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004431 return false;
4432 }
4433 break;
4434
Yunchao He61afff12017-03-14 15:34:03 +08004435 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004436 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004437 if (context->getClientVersion() < Version(3, 1))
4438 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004439 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004440 return false;
4441 }
4442 break;
4443
Jiawei Shao6ae51612018-02-23 14:03:25 +08004444 case GL_COMPUTE_WORK_GROUP_SIZE:
4445 if (context->getClientVersion() < Version(3, 1))
4446 {
4447 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4448 return false;
4449 }
4450
4451 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4452 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4453 // program which has not been linked successfully, or which does not contain objects to
4454 // form a compute shader.
4455 if (!programObject->isLinked())
4456 {
4457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4458 return false;
4459 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004460 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004461 {
4462 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4463 return false;
4464 }
4465 break;
4466
Jiawei Shao447bfac2018-03-14 14:23:40 +08004467 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4468 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4469 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4470 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4471 if (!context->getExtensions().geometryShader)
4472 {
4473 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4474 return false;
4475 }
4476
4477 // [EXT_geometry_shader] Chapter 7.12
4478 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4479 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4480 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4481 // successfully, or which does not contain objects to form a geometry shader.
4482 if (!programObject->isLinked())
4483 {
4484 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4485 return false;
4486 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004487 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004488 {
4489 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4490 return false;
4491 }
4492 break;
4493
Geoff Langff5b2d52016-09-07 11:32:23 -04004494 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004495 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
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
4678 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4679}
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
4692 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4693}
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,
4718 GLuint bufSize,
4719 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
4804 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4805}
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
4818 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4819}
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 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005056 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005057 return false;
5058 }
5059
5060 if (size < 1 || size > 4)
5061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005062 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005078 context->handleError(InvalidEnum()
5079 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005080 return false;
5081 }
5082 break;
5083
5084 case GL_FIXED:
5085 case GL_FLOAT:
5086 if (pureInteger)
5087 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005088 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005089 return false;
5090 }
5091 break;
5092
5093 case GL_HALF_FLOAT:
5094 if (context->getClientMajorVersion() < 3)
5095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005096 context->handleError(InvalidEnum()
5097 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005098 return false;
5099 }
5100 if (pureInteger)
5101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005103 return false;
5104 }
5105 break;
5106
5107 case GL_INT_2_10_10_10_REV:
5108 case GL_UNSIGNED_INT_2_10_10_10_REV:
5109 if (context->getClientMajorVersion() < 3)
5110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005111 context->handleError(InvalidEnum()
5112 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005113 return false;
5114 }
5115 if (pureInteger)
5116 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005118 return false;
5119 }
5120 if (size != 4)
5121 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005122 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5123 "UNSIGNED_INT_2_10_10_10_REV and "
5124 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005125 return false;
5126 }
5127 break;
5128
5129 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005130 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005131 return false;
5132 }
5133
5134 return true;
5135}
5136
Geoff Lang76e65652017-03-27 14:58:02 -04005137// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5138// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5139// specified clear value and the type of a buffer that is being cleared generates an
5140// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005141bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005142 GLint drawbuffer,
5143 const GLenum *validComponentTypes,
5144 size_t validComponentTypeCount)
5145{
5146 const FramebufferAttachment *attachment =
5147 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5148 if (attachment)
5149 {
5150 GLenum componentType = attachment->getFormat().info->componentType;
5151 const GLenum *end = validComponentTypes + validComponentTypeCount;
5152 if (std::find(validComponentTypes, end, componentType) == end)
5153 {
5154 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005155 InvalidOperation()
5156 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005157 return false;
5158 }
5159 }
5160
5161 return true;
5162}
5163
Jamie Madill5b772312018-03-08 20:28:32 -05005164bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005165{
5166 if (!ValidateRobustEntryPoint(context, dataSize))
5167 {
5168 return false;
5169 }
5170
Jamie Madill43da7c42018-08-01 11:34:49 -04005171 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005172 if (pixelUnpackBuffer == nullptr)
5173 {
5174 if (dataSize < imageSize)
5175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005176 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005177 }
5178 }
5179 return true;
5180}
5181
Jamie Madill5b772312018-03-08 20:28:32 -05005182bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005183 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005184 GLenum pname,
5185 bool pointerVersion,
5186 GLsizei *numParams)
5187{
5188 if (numParams)
5189 {
5190 *numParams = 0;
5191 }
5192
Corentin Walleze4477002017-12-01 14:39:58 -05005193 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005194 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005195 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005196 return false;
5197 }
5198
5199 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5200 if (!buffer)
5201 {
5202 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005204 return false;
5205 }
5206
5207 const Extensions &extensions = context->getExtensions();
5208
5209 switch (pname)
5210 {
5211 case GL_BUFFER_USAGE:
5212 case GL_BUFFER_SIZE:
5213 break;
5214
5215 case GL_BUFFER_ACCESS_OES:
5216 if (!extensions.mapBuffer)
5217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005218 context->handleError(InvalidEnum()
5219 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005220 return false;
5221 }
5222 break;
5223
5224 case GL_BUFFER_MAPPED:
5225 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5226 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5227 !extensions.mapBufferRange)
5228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005229 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5230 "GL_OES_mapbuffer or "
5231 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005232 return false;
5233 }
5234 break;
5235
5236 case GL_BUFFER_MAP_POINTER:
5237 if (!pointerVersion)
5238 {
5239 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005240 InvalidEnum()
5241 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005242 return false;
5243 }
5244 break;
5245
5246 case GL_BUFFER_ACCESS_FLAGS:
5247 case GL_BUFFER_MAP_OFFSET:
5248 case GL_BUFFER_MAP_LENGTH:
5249 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005251 context->handleError(InvalidEnum()
5252 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005253 return false;
5254 }
5255 break;
5256
5257 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005258 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005259 return false;
5260 }
5261
5262 // All buffer parameter queries return one value.
5263 if (numParams)
5264 {
5265 *numParams = 1;
5266 }
5267
5268 return true;
5269}
5270
5271bool ValidateGetRenderbufferParameterivBase(Context *context,
5272 GLenum target,
5273 GLenum pname,
5274 GLsizei *length)
5275{
5276 if (length)
5277 {
5278 *length = 0;
5279 }
5280
5281 if (target != GL_RENDERBUFFER)
5282 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005283 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005284 return false;
5285 }
5286
5287 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5288 if (renderbuffer == nullptr)
5289 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005290 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005291 return false;
5292 }
5293
5294 switch (pname)
5295 {
5296 case GL_RENDERBUFFER_WIDTH:
5297 case GL_RENDERBUFFER_HEIGHT:
5298 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5299 case GL_RENDERBUFFER_RED_SIZE:
5300 case GL_RENDERBUFFER_GREEN_SIZE:
5301 case GL_RENDERBUFFER_BLUE_SIZE:
5302 case GL_RENDERBUFFER_ALPHA_SIZE:
5303 case GL_RENDERBUFFER_DEPTH_SIZE:
5304 case GL_RENDERBUFFER_STENCIL_SIZE:
5305 break;
5306
5307 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5308 if (!context->getExtensions().framebufferMultisample)
5309 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005310 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005311 return false;
5312 }
5313 break;
5314
5315 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005316 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005317 return false;
5318 }
5319
5320 if (length)
5321 {
5322 *length = 1;
5323 }
5324 return true;
5325}
5326
5327bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5328{
5329 if (length)
5330 {
5331 *length = 0;
5332 }
5333
5334 if (GetValidShader(context, shader) == nullptr)
5335 {
5336 return false;
5337 }
5338
5339 switch (pname)
5340 {
5341 case GL_SHADER_TYPE:
5342 case GL_DELETE_STATUS:
5343 case GL_COMPILE_STATUS:
5344 case GL_INFO_LOG_LENGTH:
5345 case GL_SHADER_SOURCE_LENGTH:
5346 break;
5347
5348 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5349 if (!context->getExtensions().translatedShaderSource)
5350 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005351 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005352 return false;
5353 }
5354 break;
5355
5356 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005358 return false;
5359 }
5360
5361 if (length)
5362 {
5363 *length = 1;
5364 }
5365 return true;
5366}
5367
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005368bool ValidateGetTexParameterBase(Context *context,
5369 TextureType target,
5370 GLenum pname,
5371 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005372{
5373 if (length)
5374 {
5375 *length = 0;
5376 }
5377
5378 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5379 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005380 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005381 return false;
5382 }
5383
5384 if (context->getTargetTexture(target) == nullptr)
5385 {
5386 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005387 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005388 return false;
5389 }
5390
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005391 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5392 {
5393 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5394 return false;
5395 }
5396
Jamie Madillbe849e42017-05-02 15:49:00 -04005397 switch (pname)
5398 {
5399 case GL_TEXTURE_MAG_FILTER:
5400 case GL_TEXTURE_MIN_FILTER:
5401 case GL_TEXTURE_WRAP_S:
5402 case GL_TEXTURE_WRAP_T:
5403 break;
5404
5405 case GL_TEXTURE_USAGE_ANGLE:
5406 if (!context->getExtensions().textureUsage)
5407 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005408 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005409 return false;
5410 }
5411 break;
5412
5413 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005414 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005415 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005416 return false;
5417 }
5418 break;
5419
5420 case GL_TEXTURE_IMMUTABLE_FORMAT:
5421 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5422 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005423 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005424 return false;
5425 }
5426 break;
5427
5428 case GL_TEXTURE_WRAP_R:
5429 case GL_TEXTURE_IMMUTABLE_LEVELS:
5430 case GL_TEXTURE_SWIZZLE_R:
5431 case GL_TEXTURE_SWIZZLE_G:
5432 case GL_TEXTURE_SWIZZLE_B:
5433 case GL_TEXTURE_SWIZZLE_A:
5434 case GL_TEXTURE_BASE_LEVEL:
5435 case GL_TEXTURE_MAX_LEVEL:
5436 case GL_TEXTURE_MIN_LOD:
5437 case GL_TEXTURE_MAX_LOD:
5438 case GL_TEXTURE_COMPARE_MODE:
5439 case GL_TEXTURE_COMPARE_FUNC:
5440 if (context->getClientMajorVersion() < 3)
5441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005442 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005443 return false;
5444 }
5445 break;
5446
5447 case GL_TEXTURE_SRGB_DECODE_EXT:
5448 if (!context->getExtensions().textureSRGBDecode)
5449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005450 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005451 return false;
5452 }
5453 break;
5454
Yunchao Hebacaa712018-01-30 14:01:39 +08005455 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5456 if (context->getClientVersion() < Version(3, 1))
5457 {
5458 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5459 return false;
5460 }
5461 break;
5462
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005463 case GL_GENERATE_MIPMAP:
5464 case GL_TEXTURE_CROP_RECT_OES:
5465 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5466 // after GL_OES_draw_texture functionality implemented
5467 if (context->getClientMajorVersion() > 1)
5468 {
5469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5470 return false;
5471 }
5472 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005473 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005474 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005475 return false;
5476 }
5477
5478 if (length)
5479 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005480 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 }
5482 return true;
5483}
5484
5485bool ValidateGetVertexAttribBase(Context *context,
5486 GLuint index,
5487 GLenum pname,
5488 GLsizei *length,
5489 bool pointer,
5490 bool pureIntegerEntryPoint)
5491{
5492 if (length)
5493 {
5494 *length = 0;
5495 }
5496
5497 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005499 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005500 return false;
5501 }
5502
5503 if (index >= context->getCaps().maxVertexAttributes)
5504 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005505 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005506 return false;
5507 }
5508
5509 if (pointer)
5510 {
5511 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5512 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005513 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005514 return false;
5515 }
5516 }
5517 else
5518 {
5519 switch (pname)
5520 {
5521 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5522 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5523 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5524 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5525 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5526 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5527 case GL_CURRENT_VERTEX_ATTRIB:
5528 break;
5529
5530 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5531 static_assert(
5532 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5533 "ANGLE extension enums not equal to GL enums.");
5534 if (context->getClientMajorVersion() < 3 &&
5535 !context->getExtensions().instancedArrays)
5536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005537 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5538 "requires OpenGL ES 3.0 or "
5539 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005540 return false;
5541 }
5542 break;
5543
5544 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5545 if (context->getClientMajorVersion() < 3)
5546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005547 context->handleError(
5548 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005549 return false;
5550 }
5551 break;
5552
5553 case GL_VERTEX_ATTRIB_BINDING:
5554 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5555 if (context->getClientVersion() < ES_3_1)
5556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005557 context->handleError(InvalidEnum()
5558 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005559 return false;
5560 }
5561 break;
5562
5563 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005564 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005565 return false;
5566 }
5567 }
5568
5569 if (length)
5570 {
5571 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5572 {
5573 *length = 4;
5574 }
5575 else
5576 {
5577 *length = 1;
5578 }
5579 }
5580
5581 return true;
5582}
5583
Jamie Madill4928b7c2017-06-20 12:57:39 -04005584bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005585 GLint x,
5586 GLint y,
5587 GLsizei width,
5588 GLsizei height,
5589 GLenum format,
5590 GLenum type,
5591 GLsizei bufSize,
5592 GLsizei *length,
5593 GLsizei *columns,
5594 GLsizei *rows,
5595 void *pixels)
5596{
5597 if (length != nullptr)
5598 {
5599 *length = 0;
5600 }
5601 if (rows != nullptr)
5602 {
5603 *rows = 0;
5604 }
5605 if (columns != nullptr)
5606 {
5607 *columns = 0;
5608 }
5609
5610 if (width < 0 || height < 0)
5611 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005612 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005613 return false;
5614 }
5615
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005616 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005617
Jamie Madill427064d2018-04-13 16:20:34 -04005618 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005619 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005620 return false;
5621 }
5622
Jamie Madille98b1b52018-03-08 09:47:23 -05005623 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005624 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005625 return false;
5626 }
5627
Jamie Madill690c8eb2018-03-12 15:20:03 -04005628 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005629 ASSERT(framebuffer);
5630
5631 if (framebuffer->getReadBufferState() == GL_NONE)
5632 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005633 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005634 return false;
5635 }
5636
5637 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5638 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5639 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5640 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5641 // situation is an application error that would lead to a crash in ANGLE.
5642 if (readBuffer == nullptr)
5643 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005644 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005645 return false;
5646 }
5647
Martin Radev28031682017-07-28 14:47:56 +03005648 // ANGLE_multiview, Revision 1:
5649 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005650 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5651 // in the current read framebuffer is more than one.
5652 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005653 {
5654 context->handleError(InvalidFramebufferOperation()
5655 << "Attempting to read from a multi-view framebuffer.");
5656 return false;
5657 }
5658
Geoff Lang280ba992017-04-18 16:30:58 -04005659 if (context->getExtensions().webglCompatibility)
5660 {
5661 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5662 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5663 // and type before validating the combination of format and type. However, the
5664 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5665 // verifies that GL_INVALID_OPERATION is generated.
5666 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5667 // dEQP/WebGL.
5668 if (!ValidReadPixelsFormatEnum(context, format))
5669 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005670 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005671 return false;
5672 }
5673
5674 if (!ValidReadPixelsTypeEnum(context, type))
5675 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005676 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005677 return false;
5678 }
5679 }
5680
Jamie Madill690c8eb2018-03-12 15:20:03 -04005681 GLenum currentFormat = GL_NONE;
5682 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5683
5684 GLenum currentType = GL_NONE;
5685 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5686
Jamie Madillbe849e42017-05-02 15:49:00 -04005687 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5688
5689 bool validFormatTypeCombination =
5690 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5691
5692 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5693 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005694 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005695 return false;
5696 }
5697
5698 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005699 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005700 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5701 {
5702 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005703 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005704 return false;
5705 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005706 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5707 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5708 {
5709 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5710 return false;
5711 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005712
5713 // .. the data would be packed to the buffer object such that the memory writes required
5714 // would exceed the data store size.
5715 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005716 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005717 const auto &pack = context->getGLState().getPackState();
5718
Jamie Madillca2ff382018-07-11 09:01:17 -04005719 GLuint endByte = 0;
5720 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005721 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005723 return false;
5724 }
5725
Jamie Madillbe849e42017-05-02 15:49:00 -04005726 if (bufSize >= 0)
5727 {
5728 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5729 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005730 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005731 return false;
5732 }
5733 }
5734
5735 if (pixelPackBuffer != nullptr)
5736 {
5737 CheckedNumeric<size_t> checkedEndByte(endByte);
5738 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5739 checkedEndByte += checkedOffset;
5740
5741 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5742 {
5743 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005744 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005745 return false;
5746 }
5747 }
5748
5749 if (pixelPackBuffer == nullptr && length != nullptr)
5750 {
5751 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5752 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005754 return false;
5755 }
5756
5757 *length = static_cast<GLsizei>(endByte);
5758 }
5759
Geoff Langa953b522018-02-21 16:56:23 -05005760 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005761 angle::CheckedNumeric<int> clippedExtent(length);
5762 if (start < 0)
5763 {
5764 // "subtract" the area that is less than 0
5765 clippedExtent += start;
5766 }
5767
Geoff Langa953b522018-02-21 16:56:23 -05005768 angle::CheckedNumeric<int> readExtent = start;
5769 readExtent += length;
5770 if (!readExtent.IsValid())
5771 {
5772 return false;
5773 }
5774
5775 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005776 {
5777 // Subtract the region to the right of the read buffer
5778 clippedExtent -= (readExtent - bufferSize);
5779 }
5780
5781 if (!clippedExtent.IsValid())
5782 {
Geoff Langa953b522018-02-21 16:56:23 -05005783 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 }
5785
Geoff Langa953b522018-02-21 16:56:23 -05005786 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5787 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005788 };
5789
Geoff Langa953b522018-02-21 16:56:23 -05005790 GLsizei writtenColumns = 0;
5791 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5792 {
5793 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5794 return false;
5795 }
5796
5797 GLsizei writtenRows = 0;
5798 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5799 {
5800 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5801 return false;
5802 }
5803
Jamie Madillbe849e42017-05-02 15:49:00 -04005804 if (columns != nullptr)
5805 {
Geoff Langa953b522018-02-21 16:56:23 -05005806 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 }
5808
5809 if (rows != nullptr)
5810 {
Geoff Langa953b522018-02-21 16:56:23 -05005811 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005812 }
5813
5814 return true;
5815}
5816
5817template <typename ParamType>
5818bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005819 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005820 GLenum pname,
5821 GLsizei bufSize,
5822 const ParamType *params)
5823{
5824 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5825 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005826 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005827 return false;
5828 }
5829
5830 if (context->getTargetTexture(target) == nullptr)
5831 {
5832 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005833 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005834 return false;
5835 }
5836
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005837 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005838 if (bufSize >= 0 && bufSize < minBufSize)
5839 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005841 return false;
5842 }
5843
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005844 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5845 {
5846 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5847 return false;
5848 }
5849
Jamie Madillbe849e42017-05-02 15:49:00 -04005850 switch (pname)
5851 {
5852 case GL_TEXTURE_WRAP_R:
5853 case GL_TEXTURE_SWIZZLE_R:
5854 case GL_TEXTURE_SWIZZLE_G:
5855 case GL_TEXTURE_SWIZZLE_B:
5856 case GL_TEXTURE_SWIZZLE_A:
5857 case GL_TEXTURE_BASE_LEVEL:
5858 case GL_TEXTURE_MAX_LEVEL:
5859 case GL_TEXTURE_COMPARE_MODE:
5860 case GL_TEXTURE_COMPARE_FUNC:
5861 case GL_TEXTURE_MIN_LOD:
5862 case GL_TEXTURE_MAX_LOD:
5863 if (context->getClientMajorVersion() < 3)
5864 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005865 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005866 return false;
5867 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005868 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005870 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5871 "available without "
5872 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005873 return false;
5874 }
5875 break;
5876
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005877 case GL_GENERATE_MIPMAP:
5878 case GL_TEXTURE_CROP_RECT_OES:
5879 if (context->getClientMajorVersion() > 1)
5880 {
5881 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5882 return false;
5883 }
5884 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005885 default:
5886 break;
5887 }
5888
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005889 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005890 {
5891 switch (pname)
5892 {
5893 case GL_TEXTURE_MIN_FILTER:
5894 case GL_TEXTURE_MAG_FILTER:
5895 case GL_TEXTURE_WRAP_S:
5896 case GL_TEXTURE_WRAP_T:
5897 case GL_TEXTURE_WRAP_R:
5898 case GL_TEXTURE_MIN_LOD:
5899 case GL_TEXTURE_MAX_LOD:
5900 case GL_TEXTURE_COMPARE_MODE:
5901 case GL_TEXTURE_COMPARE_FUNC:
5902 context->handleError(InvalidEnum()
5903 << "Invalid parameter for 2D multisampled textures.");
5904 return false;
5905 }
5906 }
5907
Jamie Madillbe849e42017-05-02 15:49:00 -04005908 switch (pname)
5909 {
5910 case GL_TEXTURE_WRAP_S:
5911 case GL_TEXTURE_WRAP_T:
5912 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005913 {
5914 bool restrictedWrapModes =
5915 target == TextureType::External || target == TextureType::Rectangle;
5916 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005917 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005918 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005919 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005920 }
5921 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005922
5923 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005924 {
5925 bool restrictedMinFilter =
5926 target == TextureType::External || target == TextureType::Rectangle;
5927 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005928 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005929 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005930 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005931 }
5932 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005933
5934 case GL_TEXTURE_MAG_FILTER:
5935 if (!ValidateTextureMagFilterValue(context, params))
5936 {
5937 return false;
5938 }
5939 break;
5940
5941 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005942 if (!context->getExtensions().textureUsage)
5943 {
5944 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5945 return false;
5946 }
5947
Jamie Madillbe849e42017-05-02 15:49:00 -04005948 switch (ConvertToGLenum(params[0]))
5949 {
5950 case GL_NONE:
5951 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5952 break;
5953
5954 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005955 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005956 return false;
5957 }
5958 break;
5959
5960 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005961 {
5962 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5963 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005964 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005965 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005966 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005967 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5968 }
5969 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005970
5971 case GL_TEXTURE_MIN_LOD:
5972 case GL_TEXTURE_MAX_LOD:
5973 // any value is permissible
5974 break;
5975
5976 case GL_TEXTURE_COMPARE_MODE:
5977 if (!ValidateTextureCompareModeValue(context, params))
5978 {
5979 return false;
5980 }
5981 break;
5982
5983 case GL_TEXTURE_COMPARE_FUNC:
5984 if (!ValidateTextureCompareFuncValue(context, params))
5985 {
5986 return false;
5987 }
5988 break;
5989
5990 case GL_TEXTURE_SWIZZLE_R:
5991 case GL_TEXTURE_SWIZZLE_G:
5992 case GL_TEXTURE_SWIZZLE_B:
5993 case GL_TEXTURE_SWIZZLE_A:
5994 switch (ConvertToGLenum(params[0]))
5995 {
5996 case GL_RED:
5997 case GL_GREEN:
5998 case GL_BLUE:
5999 case GL_ALPHA:
6000 case GL_ZERO:
6001 case GL_ONE:
6002 break;
6003
6004 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006005 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006006 return false;
6007 }
6008 break;
6009
6010 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006011 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006013 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006014 return false;
6015 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006016 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006018 context->handleError(InvalidOperation()
6019 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006020 return false;
6021 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006022 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006023 {
6024 context->handleError(InvalidOperation()
6025 << "Base level must be 0 for multisampled textures.");
6026 return false;
6027 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006028 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006029 {
6030 context->handleError(InvalidOperation()
6031 << "Base level must be 0 for rectangle textures.");
6032 return false;
6033 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006034 break;
6035
6036 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006037 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006038 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006039 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006040 return false;
6041 }
6042 break;
6043
6044 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6045 if (context->getClientVersion() < Version(3, 1))
6046 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006047 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006048 return false;
6049 }
6050 switch (ConvertToGLenum(params[0]))
6051 {
6052 case GL_DEPTH_COMPONENT:
6053 case GL_STENCIL_INDEX:
6054 break;
6055
6056 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006057 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006058 return false;
6059 }
6060 break;
6061
6062 case GL_TEXTURE_SRGB_DECODE_EXT:
6063 if (!ValidateTextureSRGBDecodeValue(context, params))
6064 {
6065 return false;
6066 }
6067 break;
6068
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006069 case GL_GENERATE_MIPMAP:
6070 case GL_TEXTURE_CROP_RECT_OES:
6071 if (context->getClientMajorVersion() > 1)
6072 {
6073 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6074 return false;
6075 }
6076 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006077 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006078 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006079 return false;
6080 }
6081
6082 return true;
6083}
6084
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006085template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6086template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006087
Jamie Madill5b772312018-03-08 20:28:32 -05006088bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006089{
6090 if (index >= MAX_VERTEX_ATTRIBS)
6091 {
6092 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6093 return false;
6094 }
6095
6096 return true;
6097}
6098
6099bool ValidateGetActiveUniformBlockivBase(Context *context,
6100 GLuint program,
6101 GLuint uniformBlockIndex,
6102 GLenum pname,
6103 GLsizei *length)
6104{
6105 if (length)
6106 {
6107 *length = 0;
6108 }
6109
6110 if (context->getClientMajorVersion() < 3)
6111 {
6112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6113 return false;
6114 }
6115
6116 Program *programObject = GetValidProgram(context, program);
6117 if (!programObject)
6118 {
6119 return false;
6120 }
6121
6122 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6123 {
6124 context->handleError(InvalidValue()
6125 << "uniformBlockIndex exceeds active uniform block count.");
6126 return false;
6127 }
6128
6129 switch (pname)
6130 {
6131 case GL_UNIFORM_BLOCK_BINDING:
6132 case GL_UNIFORM_BLOCK_DATA_SIZE:
6133 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6134 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6135 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6136 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6137 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6138 break;
6139
6140 default:
6141 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6142 return false;
6143 }
6144
6145 if (length)
6146 {
6147 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6148 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006149 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006150 programObject->getUniformBlockByIndex(uniformBlockIndex);
6151 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6152 }
6153 else
6154 {
6155 *length = 1;
6156 }
6157 }
6158
6159 return true;
6160}
6161
Jamie Madill9696d072017-08-26 23:19:57 -04006162template <typename ParamType>
6163bool ValidateSamplerParameterBase(Context *context,
6164 GLuint sampler,
6165 GLenum pname,
6166 GLsizei bufSize,
6167 ParamType *params)
6168{
6169 if (context->getClientMajorVersion() < 3)
6170 {
6171 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6172 return false;
6173 }
6174
6175 if (!context->isSampler(sampler))
6176 {
6177 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6178 return false;
6179 }
6180
6181 const GLsizei minBufSize = 1;
6182 if (bufSize >= 0 && bufSize < minBufSize)
6183 {
6184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6185 return false;
6186 }
6187
6188 switch (pname)
6189 {
6190 case GL_TEXTURE_WRAP_S:
6191 case GL_TEXTURE_WRAP_T:
6192 case GL_TEXTURE_WRAP_R:
6193 if (!ValidateTextureWrapModeValue(context, params, false))
6194 {
6195 return false;
6196 }
6197 break;
6198
6199 case GL_TEXTURE_MIN_FILTER:
6200 if (!ValidateTextureMinFilterValue(context, params, false))
6201 {
6202 return false;
6203 }
6204 break;
6205
6206 case GL_TEXTURE_MAG_FILTER:
6207 if (!ValidateTextureMagFilterValue(context, params))
6208 {
6209 return false;
6210 }
6211 break;
6212
6213 case GL_TEXTURE_MIN_LOD:
6214 case GL_TEXTURE_MAX_LOD:
6215 // any value is permissible
6216 break;
6217
6218 case GL_TEXTURE_COMPARE_MODE:
6219 if (!ValidateTextureCompareModeValue(context, params))
6220 {
6221 return false;
6222 }
6223 break;
6224
6225 case GL_TEXTURE_COMPARE_FUNC:
6226 if (!ValidateTextureCompareFuncValue(context, params))
6227 {
6228 return false;
6229 }
6230 break;
6231
6232 case GL_TEXTURE_SRGB_DECODE_EXT:
6233 if (!ValidateTextureSRGBDecodeValue(context, params))
6234 {
6235 return false;
6236 }
6237 break;
6238
Luc Ferron1b1a8642018-01-23 15:12:01 -05006239 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6240 {
6241 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6242 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6243 {
6244 return false;
6245 }
6246 }
6247 break;
6248
Jamie Madill9696d072017-08-26 23:19:57 -04006249 default:
6250 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6251 return false;
6252 }
6253
6254 return true;
6255}
6256
6257template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6258template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6259
6260bool ValidateGetSamplerParameterBase(Context *context,
6261 GLuint sampler,
6262 GLenum pname,
6263 GLsizei *length)
6264{
6265 if (length)
6266 {
6267 *length = 0;
6268 }
6269
6270 if (context->getClientMajorVersion() < 3)
6271 {
6272 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6273 return false;
6274 }
6275
6276 if (!context->isSampler(sampler))
6277 {
6278 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6279 return false;
6280 }
6281
6282 switch (pname)
6283 {
6284 case GL_TEXTURE_WRAP_S:
6285 case GL_TEXTURE_WRAP_T:
6286 case GL_TEXTURE_WRAP_R:
6287 case GL_TEXTURE_MIN_FILTER:
6288 case GL_TEXTURE_MAG_FILTER:
6289 case GL_TEXTURE_MIN_LOD:
6290 case GL_TEXTURE_MAX_LOD:
6291 case GL_TEXTURE_COMPARE_MODE:
6292 case GL_TEXTURE_COMPARE_FUNC:
6293 break;
6294
Luc Ferron1b1a8642018-01-23 15:12:01 -05006295 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6296 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6297 {
6298 return false;
6299 }
6300 break;
6301
Jamie Madill9696d072017-08-26 23:19:57 -04006302 case GL_TEXTURE_SRGB_DECODE_EXT:
6303 if (!context->getExtensions().textureSRGBDecode)
6304 {
6305 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6306 return false;
6307 }
6308 break;
6309
6310 default:
6311 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6312 return false;
6313 }
6314
6315 if (length)
6316 {
6317 *length = 1;
6318 }
6319 return true;
6320}
6321
6322bool ValidateGetInternalFormativBase(Context *context,
6323 GLenum target,
6324 GLenum internalformat,
6325 GLenum pname,
6326 GLsizei bufSize,
6327 GLsizei *numParams)
6328{
6329 if (numParams)
6330 {
6331 *numParams = 0;
6332 }
6333
6334 if (context->getClientMajorVersion() < 3)
6335 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006336 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006337 return false;
6338 }
6339
6340 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006341 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006342 {
6343 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6344 return false;
6345 }
6346
6347 switch (target)
6348 {
6349 case GL_RENDERBUFFER:
6350 break;
6351
6352 case GL_TEXTURE_2D_MULTISAMPLE:
6353 if (context->getClientVersion() < ES_3_1)
6354 {
6355 context->handleError(InvalidOperation()
6356 << "Texture target requires at least OpenGL ES 3.1.");
6357 return false;
6358 }
6359 break;
6360
6361 default:
6362 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6363 return false;
6364 }
6365
6366 if (bufSize < 0)
6367 {
6368 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6369 return false;
6370 }
6371
6372 GLsizei maxWriteParams = 0;
6373 switch (pname)
6374 {
6375 case GL_NUM_SAMPLE_COUNTS:
6376 maxWriteParams = 1;
6377 break;
6378
6379 case GL_SAMPLES:
6380 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6381 break;
6382
6383 default:
6384 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6385 return false;
6386 }
6387
6388 if (numParams)
6389 {
6390 // glGetInternalFormativ will not overflow bufSize
6391 *numParams = std::min(bufSize, maxWriteParams);
6392 }
6393
6394 return true;
6395}
6396
Jamie Madille98b1b52018-03-08 09:47:23 -05006397bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6398{
Jamie Madill427064d2018-04-13 16:20:34 -04006399 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006400 {
6401 context->handleError(InvalidOperation());
6402 return false;
6403 }
6404 return true;
6405}
6406
Lingfeng Yang038dd532018-03-29 17:31:52 -07006407bool ValidateMultitextureUnit(Context *context, GLenum texture)
6408{
6409 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6410 {
6411 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6412 return false;
6413 }
6414 return true;
6415}
6416
Jamie Madillc29968b2016-01-20 11:17:23 -05006417} // namespace gl