blob: ca6dedf98d768282bbce1d51cbdf85acf6b470a8 [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
86 const gl::State &state = context->getGLState();
87
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 Madilla2d1d2d2018-08-01 11:34:46 -0400120 // An overflow can happen when adding the offset. Negative indicates overflow.
121 if (context->getStateCache().getNonInstancedVertexElementLimit() < 0 ||
122 context->getStateCache().getInstancedVertexElementLimit() < 0)
123 {
124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
125 return false;
126 }
127
128 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
129 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
130 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
131 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400132}
133
Jamie Madill5b772312018-03-08 20:28:32 -0500134bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400135{
136 switch (type)
137 {
138 // Types referenced in Table 3.4 of the ES 2.0.25 spec
139 case GL_UNSIGNED_BYTE:
140 case GL_UNSIGNED_SHORT_4_4_4_4:
141 case GL_UNSIGNED_SHORT_5_5_5_1:
142 case GL_UNSIGNED_SHORT_5_6_5:
143 return context->getClientVersion() >= ES_2_0;
144
145 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
146 case GL_BYTE:
147 case GL_INT:
148 case GL_SHORT:
149 case GL_UNSIGNED_INT:
150 case GL_UNSIGNED_INT_10F_11F_11F_REV:
151 case GL_UNSIGNED_INT_24_8:
152 case GL_UNSIGNED_INT_2_10_10_10_REV:
153 case GL_UNSIGNED_INT_5_9_9_9_REV:
154 case GL_UNSIGNED_SHORT:
155 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
156 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
157 return context->getClientVersion() >= ES_3_0;
158
159 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400160 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
161 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400162
163 case GL_HALF_FLOAT:
164 return context->getClientVersion() >= ES_3_0 ||
165 context->getExtensions().textureHalfFloat;
166
167 case GL_HALF_FLOAT_OES:
168 return context->getExtensions().colorBufferHalfFloat;
169
170 default:
171 return false;
172 }
173}
174
Jamie Madill5b772312018-03-08 20:28:32 -0500175bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400176{
177 switch (format)
178 {
179 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
180 case GL_RGBA:
181 case GL_RGB:
182 case GL_ALPHA:
183 return context->getClientVersion() >= ES_2_0;
184
185 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
186 case GL_RG:
187 case GL_RED:
188 case GL_RGBA_INTEGER:
189 case GL_RGB_INTEGER:
190 case GL_RG_INTEGER:
191 case GL_RED_INTEGER:
192 return context->getClientVersion() >= ES_3_0;
193
194 case GL_SRGB_ALPHA_EXT:
195 case GL_SRGB_EXT:
196 return context->getExtensions().sRGB;
197
198 case GL_BGRA_EXT:
199 return context->getExtensions().readFormatBGRA;
200
201 default:
202 return false;
203 }
204}
205
Jamie Madill5b772312018-03-08 20:28:32 -0500206bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400207 GLenum framebufferComponentType,
208 GLenum format,
209 GLenum type)
210{
211 switch (framebufferComponentType)
212 {
213 case GL_UNSIGNED_NORMALIZED:
214 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
215 // ReadPixels with BGRA even if the extension is not present
216 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
217 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
218 type == GL_UNSIGNED_BYTE);
219
220 case GL_SIGNED_NORMALIZED:
221 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
222
223 case GL_INT:
224 return (format == GL_RGBA_INTEGER && type == GL_INT);
225
226 case GL_UNSIGNED_INT:
227 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
228
229 case GL_FLOAT:
230 return (format == GL_RGBA && type == GL_FLOAT);
231
232 default:
233 UNREACHABLE();
234 return false;
235 }
236}
237
Geoff Langc1984ed2016-10-07 12:41:00 -0400238template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400239bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400240{
241 switch (ConvertToGLenum(params[0]))
242 {
243 case GL_CLAMP_TO_EDGE:
244 break;
245
246 case GL_REPEAT:
247 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400248 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400249 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400250 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700251 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400252 return false;
253 }
254 break;
255
256 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700257 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400258 return false;
259 }
260
261 return true;
262}
263
264template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400265bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400266{
267 switch (ConvertToGLenum(params[0]))
268 {
269 case GL_NEAREST:
270 case GL_LINEAR:
271 break;
272
273 case GL_NEAREST_MIPMAP_NEAREST:
274 case GL_LINEAR_MIPMAP_NEAREST:
275 case GL_NEAREST_MIPMAP_LINEAR:
276 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400277 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400278 {
279 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700280 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400281 return false;
282 }
283 break;
284
285 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700286 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400287 return false;
288 }
289
290 return true;
291}
292
293template <typename ParamType>
294bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
295{
296 switch (ConvertToGLenum(params[0]))
297 {
298 case GL_NEAREST:
299 case GL_LINEAR:
300 break;
301
302 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700303 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400304 return false;
305 }
306
307 return true;
308}
309
310template <typename ParamType>
311bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
312{
313 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
314 switch (ConvertToGLenum(params[0]))
315 {
316 case GL_NONE:
317 case GL_COMPARE_REF_TO_TEXTURE:
318 break;
319
320 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400322 return false;
323 }
324
325 return true;
326}
327
328template <typename ParamType>
329bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
330{
331 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
332 switch (ConvertToGLenum(params[0]))
333 {
334 case GL_LEQUAL:
335 case GL_GEQUAL:
336 case GL_LESS:
337 case GL_GREATER:
338 case GL_EQUAL:
339 case GL_NOTEQUAL:
340 case GL_ALWAYS:
341 case GL_NEVER:
342 break;
343
344 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700345 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400346 return false;
347 }
348
349 return true;
350}
351
352template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700353bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
354{
355 if (!context->getExtensions().textureSRGBDecode)
356 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700358 return false;
359 }
360
361 switch (ConvertToGLenum(params[0]))
362 {
363 case GL_DECODE_EXT:
364 case GL_SKIP_DECODE_EXT:
365 break;
366
367 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700368 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700369 return false;
370 }
371
372 return true;
373}
374
Luc Ferron1b1a8642018-01-23 15:12:01 -0500375bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
376{
377 if (!context->getExtensions().textureFilterAnisotropic)
378 {
379 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
380 return false;
381 }
382
383 return true;
384}
385
386bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
387{
388 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
389 {
390 return false;
391 }
392
393 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
394
395 if (paramValue < 1 || paramValue > largest)
396 {
397 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
398 return false;
399 }
400
401 return true;
402}
403
Jamie Madill5b772312018-03-08 20:28:32 -0500404bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400405{
406 const Program *program = context->getGLState().getProgram();
407 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
408
Brandon Jonesc405ae72017-12-06 14:15:03 -0800409 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
410 framebuffer->getDrawBufferTypeMask().to_ulong(),
411 program->getActiveOutputVariables().to_ulong(),
412 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400413 {
Brandon Jones76746f92017-11-22 11:44:41 -0800414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
415 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400416 }
417
418 return true;
419}
420
Jamie Madill5b772312018-03-08 20:28:32 -0500421bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400422{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700423 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400424 const Program *program = context->getGLState().getProgram();
425 const VertexArray *vao = context->getGLState().getVertexArray();
426
Brandon Jonesc405ae72017-12-06 14:15:03 -0800427 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
428 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
429 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
430
431 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
432 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
433 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
434
435 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
436 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400437 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800438 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
439 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400440 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400441 return true;
442}
443
Jamie Madill493f9572018-05-24 19:52:15 -0400444bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
445 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800446{
447 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400448 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800449 {
Jamie Madill493f9572018-05-24 19:52:15 -0400450 case PrimitiveMode::Points:
451 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
452 case PrimitiveMode::Lines:
453 case PrimitiveMode::LineStrip:
454 case PrimitiveMode::LineLoop:
455 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
456 case PrimitiveMode::LinesAdjacency:
457 case PrimitiveMode::LineStripAdjacency:
458 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
459 case PrimitiveMode::Triangles:
460 case PrimitiveMode::TriangleFan:
461 case PrimitiveMode::TriangleStrip:
462 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
463 case PrimitiveMode::TrianglesAdjacency:
464 case PrimitiveMode::TriangleStripAdjacency:
465 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800466 default:
467 UNREACHABLE();
468 return false;
469 }
470}
471
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700472// GLES1 texture parameters are a small subset of the others
473bool IsValidGLES1TextureParameter(GLenum pname)
474{
475 switch (pname)
476 {
477 case GL_TEXTURE_MAG_FILTER:
478 case GL_TEXTURE_MIN_FILTER:
479 case GL_TEXTURE_WRAP_S:
480 case GL_TEXTURE_WRAP_T:
481 case GL_TEXTURE_WRAP_R:
482 case GL_GENERATE_MIPMAP:
483 case GL_TEXTURE_CROP_RECT_OES:
484 return true;
485 default:
486 return false;
487 }
488}
489
Geoff Langf41a7152016-09-19 15:11:17 -0400490} // anonymous namespace
491
Brandon Jonesd1049182018-03-28 10:02:20 -0700492void SetRobustLengthParam(GLsizei *length, GLsizei value)
493{
494 if (length)
495 {
496 *length = value;
497 }
498}
499
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500500bool IsETC2EACFormat(const GLenum format)
501{
502 // ES 3.1, Table 8.19
503 switch (format)
504 {
505 case GL_COMPRESSED_R11_EAC:
506 case GL_COMPRESSED_SIGNED_R11_EAC:
507 case GL_COMPRESSED_RG11_EAC:
508 case GL_COMPRESSED_SIGNED_RG11_EAC:
509 case GL_COMPRESSED_RGB8_ETC2:
510 case GL_COMPRESSED_SRGB8_ETC2:
511 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
512 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
513 case GL_COMPRESSED_RGBA8_ETC2_EAC:
514 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
515 return true;
516
517 default:
518 return false;
519 }
520}
521
Jamie Madill5b772312018-03-08 20:28:32 -0500522bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400523{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800524 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400525 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800526 case TextureType::_2D:
527 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800528 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400529
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800530 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400531 return context->getExtensions().textureRectangle;
532
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800533 case TextureType::_3D:
534 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800535 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500536
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800537 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800538 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400539
He Yunchaoced53ae2016-11-29 15:00:51 +0800540 default:
541 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500542 }
Jamie Madill35d15012013-10-07 10:46:37 -0400543}
544
Jamie Madill5b772312018-03-08 20:28:32 -0500545bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500546{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800547 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500548 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800549 case TextureType::_2D:
550 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500551 return true;
552
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800553 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400554 return context->getExtensions().textureRectangle;
555
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500556 default:
557 return false;
558 }
559}
560
Jamie Madill5b772312018-03-08 20:28:32 -0500561bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500562{
563 switch (target)
564 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800565 case TextureType::_3D:
566 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300567 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500568
569 default:
570 return false;
571 }
572}
573
Ian Ewellbda75592016-04-18 17:25:54 -0400574// Most texture GL calls are not compatible with external textures, so we have a separate validation
575// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500576bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400577{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800578 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400579 (context->getExtensions().eglImageExternal ||
580 context->getExtensions().eglStreamConsumerExternal);
581}
582
Shannon Woods4dfed832014-03-17 20:03:39 -0400583// This function differs from ValidTextureTarget in that the target must be
584// usable as the destination of a 2D operation-- so a cube face is valid, but
585// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400586// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500587bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400588{
589 switch (target)
590 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800591 case TextureTarget::_2D:
592 case TextureTarget::CubeMapNegativeX:
593 case TextureTarget::CubeMapNegativeY:
594 case TextureTarget::CubeMapNegativeZ:
595 case TextureTarget::CubeMapPositiveX:
596 case TextureTarget::CubeMapPositiveY:
597 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800598 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800599 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400600 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800601 default:
602 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500603 }
604}
605
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800606bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400607 PrimitiveMode transformFeedbackPrimitiveMode,
608 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800609{
610 ASSERT(context);
611
612 if (!context->getExtensions().geometryShader)
613 {
614 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
615 // that does not match the current transform feedback object's draw mode (if transform
616 // feedback is active), (3.0.2, section 2.14, pg 86)
617 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
618 }
619
620 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400621 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800622 {
Jamie Madill493f9572018-05-24 19:52:15 -0400623 case PrimitiveMode::Points:
624 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
625 case PrimitiveMode::Lines:
626 case PrimitiveMode::LineStrip:
627 case PrimitiveMode::LineLoop:
628 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
629 case PrimitiveMode::Triangles:
630 case PrimitiveMode::TriangleFan:
631 case PrimitiveMode::TriangleStrip:
632 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800633 default:
634 UNREACHABLE();
635 return false;
636 }
637}
638
Jamie Madill5b772312018-03-08 20:28:32 -0500639bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400640 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400641 GLsizei count,
642 GLenum type,
643 const GLvoid *indices,
644 GLsizei primcount)
645{
646 if (primcount < 0)
647 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700648 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400649 return false;
650 }
651
652 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
653 {
654 return false;
655 }
656
Jamie Madill9fdaa492018-02-16 10:52:11 -0500657 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400658}
659
660bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400661 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400662 GLint first,
663 GLsizei count,
664 GLsizei primcount)
665{
666 if (primcount < 0)
667 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700668 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400669 return false;
670 }
671
672 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
673 {
674 return false;
675 }
676
Jamie Madill9fdaa492018-02-16 10:52:11 -0500677 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400678}
679
Jamie Madill5b772312018-03-08 20:28:32 -0500680bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400681{
682 // Verify there is at least one active attribute with a divisor of zero
683 const State &state = context->getGLState();
684
685 Program *program = state.getProgram();
686
687 const auto &attribs = state.getVertexArray()->getVertexAttributes();
688 const auto &bindings = state.getVertexArray()->getVertexBindings();
689 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
690 {
691 const VertexAttribute &attrib = attribs[attributeIndex];
692 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300693 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400694 {
695 return true;
696 }
697 }
698
Brandon Jonesafa75152017-07-21 13:11:29 -0700699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400700 return false;
701}
702
Jamie Madill5b772312018-03-08 20:28:32 -0500703bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500704{
705 switch (target)
706 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800707 case TextureType::_3D:
708 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800709 return true;
710 default:
711 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400712 }
713}
714
Jamie Madill5b772312018-03-08 20:28:32 -0500715bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800716{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800717 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800718 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800719 case TextureType::_2D:
720 case TextureType::_2DArray:
721 case TextureType::_2DMultisample:
722 case TextureType::CubeMap:
723 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800724 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800725 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400726 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800727 default:
728 return false;
729 }
730}
731
Jamie Madill5b772312018-03-08 20:28:32 -0500732bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500733{
He Yunchaoced53ae2016-11-29 15:00:51 +0800734 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
735 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400736 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500737
738 switch (target)
739 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800740 case GL_FRAMEBUFFER:
741 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400742
He Yunchaoced53ae2016-11-29 15:00:51 +0800743 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800744 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400745 return (context->getExtensions().framebufferBlit ||
746 context->getClientMajorVersion() >= 3);
747
He Yunchaoced53ae2016-11-29 15:00:51 +0800748 default:
749 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500750 }
751}
752
Jamie Madill5b772312018-03-08 20:28:32 -0500753bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400754{
Jamie Madillc29968b2016-01-20 11:17:23 -0500755 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400756 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800757 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400758 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800759 case TextureType::_2D:
760 case TextureType::_2DArray:
761 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500762 maxDimension = caps.max2DTextureSize;
763 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800764 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800765 maxDimension = caps.maxCubeMapTextureSize;
766 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800767 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400768 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800769 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800770 maxDimension = caps.max3DTextureSize;
771 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800772 default:
773 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400774 }
775
Brandon Jones6cad5662017-06-14 13:25:13 -0700776 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400777}
778
Jamie Madill5b772312018-03-08 20:28:32 -0500779bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800780 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700781 GLint level,
782 GLsizei width,
783 GLsizei height,
784 GLsizei depth,
785 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400786{
Brandon Jones6cad5662017-06-14 13:25:13 -0700787 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400788 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700789 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400790 return false;
791 }
Austin Kinross08528e12015-10-07 16:24:40 -0700792 // TexSubImage parameters can be NPOT without textureNPOT extension,
793 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500794 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500795 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500796 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400797 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400798 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700799 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400800 return false;
801 }
802
803 if (!ValidMipLevel(context, target, level))
804 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700805 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400806 return false;
807 }
808
809 return true;
810}
811
Geoff Lang966c9402017-04-18 12:38:27 -0400812bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
813{
814 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
815 (size % blockSize == 0);
816}
817
Jamie Madill5b772312018-03-08 20:28:32 -0500818bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500819 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400820 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500821 GLsizei width,
822 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400823{
Geoff Langca271392017-04-05 12:30:00 -0400824 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400825 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400826 {
827 return false;
828 }
829
Geoff Lang966c9402017-04-18 12:38:27 -0400830 if (width < 0 || height < 0)
831 {
832 return false;
833 }
834
835 if (CompressedTextureFormatRequiresExactSize(internalFormat))
836 {
837 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
838 // block size for level 0 but WebGL disallows this.
839 bool smallerThanBlockSizeAllowed =
840 level > 0 || !context->getExtensions().webglCompatibility;
841
842 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
843 smallerThanBlockSizeAllowed) ||
844 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
845 smallerThanBlockSizeAllowed))
846 {
847 return false;
848 }
849 }
850
851 return true;
852}
853
Jamie Madill5b772312018-03-08 20:28:32 -0500854bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400855 GLenum internalFormat,
856 GLint xoffset,
857 GLint yoffset,
858 GLsizei width,
859 GLsizei height,
860 size_t textureWidth,
861 size_t textureHeight)
862{
863 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
864 if (!formatInfo.compressed)
865 {
866 return false;
867 }
868
Geoff Lang44ff5a72017-02-03 15:15:43 -0500869 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400870 {
871 return false;
872 }
873
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500874 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400875 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500876 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400877 yoffset % formatInfo.compressedBlockHeight != 0)
878 {
879 return false;
880 }
881
882 // Allowed to either have data that is a multiple of block size or is smaller than the block
883 // size but fills the entire mip
884 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
885 static_cast<size_t>(width) == textureWidth &&
886 static_cast<size_t>(height) == textureHeight;
887 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
888 (height % formatInfo.compressedBlockHeight) == 0;
889 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400890 {
891 return false;
892 }
893 }
894
Geoff Langd4f180b2013-09-24 13:57:44 -0400895 return true;
896}
897
Jamie Madill5b772312018-03-08 20:28:32 -0500898bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800899 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400900 GLsizei width,
901 GLsizei height,
902 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400903 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400904 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400905 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400906 GLsizei imageSize)
907{
Corentin Wallez336129f2017-10-17 15:55:40 -0400908 gl::Buffer *pixelUnpackBuffer =
909 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400910 if (pixelUnpackBuffer == nullptr && imageSize < 0)
911 {
912 // Checks are not required
913 return true;
914 }
915
916 // ...the data would be unpacked from the buffer object such that the memory reads required
917 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400918 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
919 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400920 const gl::Extents size(width, height, depth);
921 const auto &unpack = context->getGLState().getUnpackState();
922
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800923 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400924 GLuint endByte = 0;
925 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400926 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400927 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400928 return false;
929 }
930
Geoff Langff5b2d52016-09-07 11:32:23 -0400931 if (pixelUnpackBuffer)
932 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400933 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400934 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
935 checkedEndByte += checkedOffset;
936
937 if (!checkedEndByte.IsValid() ||
938 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
939 {
940 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400941 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400942 return false;
943 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800944 if (context->getExtensions().webglCompatibility &&
945 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
946 {
947 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
948 PixelUnpackBufferBoundForTransformFeedback);
949 return false;
950 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400951 }
952 else
953 {
954 ASSERT(imageSize >= 0);
955 if (pixels == nullptr && imageSize != 0)
956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500957 context->handleError(InvalidOperation()
958 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400959 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400960 }
961
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400962 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500964 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400965 return false;
966 }
967 }
968
969 return true;
970}
971
Corentin Wallezad3ae902018-03-09 13:40:42 -0500972bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500973{
Geoff Lang37dde692014-01-31 16:34:54 -0500974 switch (queryType)
975 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500976 case QueryType::AnySamples:
977 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400978 return context->getClientMajorVersion() >= 3 ||
979 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500980 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800981 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500982 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800983 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500984 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500986 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800987 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800988 default:
989 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500990 }
991}
992
Jamie Madill5b772312018-03-08 20:28:32 -0500993bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400994 GLenum type,
995 GLboolean normalized,
996 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400997 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400998 bool pureInteger)
999{
1000 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001001 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1002 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1003 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1004 // parameter exceeds 255.
1005 constexpr GLsizei kMaxWebGLStride = 255;
1006 if (stride > kMaxWebGLStride)
1007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001008 context->handleError(InvalidValue()
1009 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001010 return false;
1011 }
1012
1013 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1014 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1015 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1016 // or an INVALID_OPERATION error is generated.
1017 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1018 size_t typeSize = GetVertexFormatTypeSize(internalType);
1019
1020 ASSERT(isPow2(typeSize) && typeSize > 0);
1021 size_t sizeMask = (typeSize - 1);
1022 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001024 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001025 return false;
1026 }
1027
1028 if ((stride & sizeMask) != 0)
1029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001031 return false;
1032 }
1033
1034 return true;
1035}
1036
Jamie Madill5b772312018-03-08 20:28:32 -05001037Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001038{
He Yunchaoced53ae2016-11-29 15:00:51 +08001039 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1040 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1041 // or program object and INVALID_OPERATION if the provided name identifies an object
1042 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001043
Dian Xiang769769a2015-09-09 15:20:08 -07001044 Program *validProgram = context->getProgram(id);
1045
1046 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001047 {
Dian Xiang769769a2015-09-09 15:20:08 -07001048 if (context->getShader(id))
1049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001051 }
1052 else
1053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001054 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001055 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001056 }
Dian Xiang769769a2015-09-09 15:20:08 -07001057
1058 return validProgram;
1059}
1060
Jamie Madill5b772312018-03-08 20:28:32 -05001061Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001062{
1063 // See ValidProgram for spec details.
1064
1065 Shader *validShader = context->getShader(id);
1066
1067 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001068 {
Dian Xiang769769a2015-09-09 15:20:08 -07001069 if (context->getProgram(id))
1070 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001072 }
1073 else
1074 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001075 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001076 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001077 }
Dian Xiang769769a2015-09-09 15:20:08 -07001078
1079 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001080}
1081
Geoff Langb1196682014-07-23 13:47:29 -04001082bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001083{
Geoff Langfa125c92017-10-24 13:01:46 -04001084 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001085 {
Geoff Langfa125c92017-10-24 13:01:46 -04001086 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1087 {
1088 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1089 return false;
1090 }
Jamie Madillb4472272014-07-03 10:38:55 -04001091
Geoff Langfa125c92017-10-24 13:01:46 -04001092 // Color attachment 0 is validated below because it is always valid
1093 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001094 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001095 {
Geoff Langfa125c92017-10-24 13:01:46 -04001096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001097 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001098 }
1099 }
1100 else
1101 {
1102 switch (attachment)
1103 {
Geoff Langfa125c92017-10-24 13:01:46 -04001104 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001105 case GL_DEPTH_ATTACHMENT:
1106 case GL_STENCIL_ATTACHMENT:
1107 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001108
He Yunchaoced53ae2016-11-29 15:00:51 +08001109 case GL_DEPTH_STENCIL_ATTACHMENT:
1110 if (!context->getExtensions().webglCompatibility &&
1111 context->getClientMajorVersion() < 3)
1112 {
Geoff Langfa125c92017-10-24 13:01:46 -04001113 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 return false;
1115 }
1116 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001117
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001121 }
1122 }
1123
1124 return true;
1125}
1126
Jamie Madill5b772312018-03-08 20:28:32 -05001127bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001128 GLenum target,
1129 GLsizei samples,
1130 GLenum internalformat,
1131 GLsizei width,
1132 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133{
1134 switch (target)
1135 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001136 case GL_RENDERBUFFER:
1137 break;
1138 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001140 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 }
1142
1143 if (width < 0 || height < 0 || samples < 0)
1144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001145 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001149 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1150 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1151
1152 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001153 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001155 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158
1159 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1160 // 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 -08001161 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001162 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1163 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001167 }
1168
Geoff Langaae65a42014-05-26 12:43:44 -04001169 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001175 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 if (handle == 0)
1177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001179 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001180 }
1181
1182 return true;
1183}
1184
He Yunchaoced53ae2016-11-29 15:00:51 +08001185bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1186 GLenum target,
1187 GLenum attachment,
1188 GLenum renderbuffertarget,
1189 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001190{
Geoff Lange8afa902017-09-27 15:00:43 -04001191 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001193 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001194 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001195 }
1196
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001197 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001198
Jamie Madill84115c92015-04-23 15:00:07 -04001199 ASSERT(framebuffer);
1200 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001203 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001204 }
1205
Jamie Madillb4472272014-07-03 10:38:55 -04001206 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207 {
Jamie Madillb4472272014-07-03 10:38:55 -04001208 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001209 }
1210
Jamie Madillab9d82c2014-01-21 16:38:14 -05001211 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1212 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1213 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1214 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1215 if (renderbuffer != 0)
1216 {
1217 if (!context->getRenderbuffer(renderbuffer))
1218 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001220 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001221 }
1222 }
1223
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001224 return true;
1225}
1226
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001227bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001228 GLint srcX0,
1229 GLint srcY0,
1230 GLint srcX1,
1231 GLint srcY1,
1232 GLint dstX0,
1233 GLint dstY0,
1234 GLint dstX1,
1235 GLint dstY1,
1236 GLbitfield mask,
1237 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001238{
1239 switch (filter)
1240 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001241 case GL_NEAREST:
1242 break;
1243 case GL_LINEAR:
1244 break;
1245 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001246 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001247 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001248 }
1249
1250 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001252 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 }
1255
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1257 // color buffer, leaving only nearest being unfiltered from above
1258 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001261 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 }
1263
Jamie Madill51f40ec2016-06-15 14:06:00 -04001264 const auto &glState = context->getGLState();
1265 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1266 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001267
1268 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001270 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001271 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001272 }
1273
Jamie Madill427064d2018-04-13 16:20:34 -04001274 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001275 {
Jamie Madill48faf802014-11-06 15:27:22 -05001276 return false;
1277 }
1278
Jamie Madill427064d2018-04-13 16:20:34 -04001279 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001280 {
Jamie Madill48faf802014-11-06 15:27:22 -05001281 return false;
1282 }
1283
Qin Jiajiaaef92162018-02-27 13:51:44 +08001284 if (readFramebuffer->id() == drawFramebuffer->id())
1285 {
1286 context->handleError(InvalidOperation());
1287 return false;
1288 }
1289
Jamie Madille98b1b52018-03-08 09:47:23 -05001290 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 {
Geoff Langb1196682014-07-23 13:47:29 -04001292 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 }
1294
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001295 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1296 // always run it in order to avoid triggering driver bugs.
1297 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1298 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001299 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001300 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1301 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001302 }
1303
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1305
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306 if (mask & GL_COLOR_BUFFER_BIT)
1307 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001308 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001309 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310
He Yunchao66a41a22016-12-15 16:45:05 +08001311 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001313 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314
Geoff Langa15472a2015-08-11 11:48:03 -04001315 for (size_t drawbufferIdx = 0;
1316 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001317 {
Geoff Langa15472a2015-08-11 11:48:03 -04001318 const FramebufferAttachment *attachment =
1319 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1320 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001321 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001322 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323
Geoff Langb2f3d052013-08-13 12:49:27 -04001324 // The GL ES 3.0.2 spec (pg 193) states that:
1325 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001326 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1327 // as well
1328 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1329 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001330 // Changes with EXT_color_buffer_float:
1331 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001332 GLenum readComponentType = readFormat.info->componentType;
1333 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001334 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001335 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001336 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001337 drawComponentType == GL_SIGNED_NORMALIZED);
1338
1339 if (extensions.colorBufferFloat)
1340 {
1341 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1342 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1343
1344 if (readFixedOrFloat != drawFixedOrFloat)
1345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001346 context->handleError(InvalidOperation()
1347 << "If the read buffer contains fixed-point or "
1348 "floating-point values, the draw buffer must "
1349 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001350 return false;
1351 }
1352 }
1353 else if (readFixedPoint != drawFixedPoint)
1354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001355 context->handleError(InvalidOperation()
1356 << "If the read buffer contains fixed-point values, "
1357 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001358 return false;
1359 }
1360
1361 if (readComponentType == GL_UNSIGNED_INT &&
1362 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 }
1367
Jamie Madill6163c752015-12-07 16:32:59 -05001368 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001371 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 }
1373
Jamie Madilla3944d42016-07-22 22:13:26 -04001374 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001375 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001378 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 }
Geoff Lange4915782017-04-12 15:19:07 -04001380
1381 if (context->getExtensions().webglCompatibility &&
1382 *readColorBuffer == *attachment)
1383 {
1384 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 InvalidOperation()
1386 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001387 return false;
1388 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
1390 }
1391
Jamie Madilla3944d42016-07-22 22:13:26 -04001392 if ((readFormat.info->componentType == GL_INT ||
1393 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1394 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001396 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 }
He Yunchao66a41a22016-12-15 16:45:05 +08001400 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1401 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1402 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1403 // situation is an application error that would lead to a crash in ANGLE.
1404 else if (drawFramebuffer->hasEnabledDrawBuffer())
1405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(
1407 InvalidOperation()
1408 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001409 return false;
1410 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
1412
He Yunchaoced53ae2016-11-29 15:00:51 +08001413 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001414 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1415 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001417 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001419 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001420 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001421 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001422 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001423
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001424 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 {
Kenneth Russell69382852017-07-21 16:38:44 -04001426 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001428 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001431
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001432 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001434 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001435 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 }
Geoff Lange4915782017-04-12 15:19:07 -04001437
1438 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001440 context->handleError(
1441 InvalidOperation()
1442 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001443 return false;
1444 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 }
He Yunchao66a41a22016-12-15 16:45:05 +08001446 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1447 else if (drawBuffer)
1448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001449 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1450 "depth/stencil attachment of a "
1451 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001452 return false;
1453 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
1455 }
1456
Martin Radeva3ed4572017-07-27 18:29:37 +03001457 // ANGLE_multiview, Revision 1:
1458 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001459 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1460 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1461 // views in the current read framebuffer is more than one.
1462 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001463 {
1464 context->handleError(InvalidFramebufferOperation()
1465 << "Attempt to read from a multi-view framebuffer.");
1466 return false;
1467 }
1468 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1469 {
1470 context->handleError(InvalidFramebufferOperation()
1471 << "Attempt to write to a multi-view framebuffer.");
1472 return false;
1473 }
1474
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001475 return true;
1476}
1477
Jamie Madill4928b7c2017-06-20 12:57:39 -04001478bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001479 GLint x,
1480 GLint y,
1481 GLsizei width,
1482 GLsizei height,
1483 GLenum format,
1484 GLenum type,
1485 GLsizei bufSize,
1486 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001487 GLsizei *columns,
1488 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001489 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001490{
1491 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001492 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 return false;
1494 }
1495
Brandon Jonesd1049182018-03-28 10:02:20 -07001496 GLsizei writeLength = 0;
1497 GLsizei writeColumns = 0;
1498 GLsizei writeRows = 0;
1499
1500 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1501 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001502 {
Geoff Langb1196682014-07-23 13:47:29 -04001503 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001504 }
1505
Brandon Jonesd1049182018-03-28 10:02:20 -07001506 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001507 {
Geoff Langb1196682014-07-23 13:47:29 -04001508 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001509 }
1510
Brandon Jonesd1049182018-03-28 10:02:20 -07001511 SetRobustLengthParam(length, writeLength);
1512 SetRobustLengthParam(columns, writeColumns);
1513 SetRobustLengthParam(rows, writeRows);
1514
Jamie Madillc29968b2016-01-20 11:17:23 -05001515 return true;
1516}
1517
1518bool ValidateReadnPixelsEXT(Context *context,
1519 GLint x,
1520 GLint y,
1521 GLsizei width,
1522 GLsizei height,
1523 GLenum format,
1524 GLenum type,
1525 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001526 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001527{
1528 if (bufSize < 0)
1529 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001530 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001531 return false;
1532 }
1533
Geoff Lang62fce5b2016-09-30 10:46:35 -04001534 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001535 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001536}
Jamie Madill26e91952014-03-05 15:01:27 -05001537
Jamie Madill4928b7c2017-06-20 12:57:39 -04001538bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001539 GLint x,
1540 GLint y,
1541 GLsizei width,
1542 GLsizei height,
1543 GLenum format,
1544 GLenum type,
1545 GLsizei bufSize,
1546 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001547 GLsizei *columns,
1548 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001549 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001550{
Brandon Jonesd1049182018-03-28 10:02:20 -07001551 GLsizei writeLength = 0;
1552 GLsizei writeColumns = 0;
1553 GLsizei writeRows = 0;
1554
Geoff Lang62fce5b2016-09-30 10:46:35 -04001555 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001556 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001557 return false;
1558 }
1559
Brandon Jonesd1049182018-03-28 10:02:20 -07001560 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1561 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001562 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001563 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001564 }
1565
Brandon Jonesd1049182018-03-28 10:02:20 -07001566 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001567 {
1568 return false;
1569 }
1570
Brandon Jonesd1049182018-03-28 10:02:20 -07001571 SetRobustLengthParam(length, writeLength);
1572 SetRobustLengthParam(columns, writeColumns);
1573 SetRobustLengthParam(rows, writeRows);
1574
Geoff Lang62fce5b2016-09-30 10:46:35 -04001575 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001576}
1577
Jamie Madillf0e04492017-08-26 15:28:42 -04001578bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001579{
1580 if (!context->getExtensions().occlusionQueryBoolean &&
1581 !context->getExtensions().disjointTimerQuery)
1582 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001583 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001584 return false;
1585 }
1586
Olli Etuaho41997e72016-03-10 13:38:39 +02001587 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001588}
1589
Jamie Madillf0e04492017-08-26 15:28:42 -04001590bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001591{
1592 if (!context->getExtensions().occlusionQueryBoolean &&
1593 !context->getExtensions().disjointTimerQuery)
1594 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001595 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001596 return false;
1597 }
1598
Olli Etuaho41997e72016-03-10 13:38:39 +02001599 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001600}
1601
Jamie Madillf0e04492017-08-26 15:28:42 -04001602bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1603{
1604 if (!context->getExtensions().occlusionQueryBoolean &&
1605 !context->getExtensions().disjointTimerQuery)
1606 {
1607 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1608 return false;
1609 }
1610
1611 return true;
1612}
1613
Corentin Wallezad3ae902018-03-09 13:40:42 -05001614bool ValidateBeginQueryBase(gl::Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001615{
1616 if (!ValidQueryType(context, target))
1617 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001618 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001619 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001620 }
1621
1622 if (id == 0)
1623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001624 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001625 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001626 }
1627
1628 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1629 // of zero, if the active query object name for <target> is non-zero (for the
1630 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1631 // the active query for either target is non-zero), if <id> is the name of an
1632 // existing query object whose type does not match <target>, or if <id> is the
1633 // active query object name for any query type, the error INVALID_OPERATION is
1634 // generated.
1635
1636 // Ensure no other queries are active
1637 // NOTE: If other queries than occlusion are supported, we will need to check
1638 // separately that:
1639 // a) The query ID passed is not the current active query for any target/type
1640 // b) There are no active queries for the requested target (and in the case
1641 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1642 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001643
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001644 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001646 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001647 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001648 }
1649
1650 Query *queryObject = context->getQuery(id, true, target);
1651
1652 // check that name was obtained with glGenQueries
1653 if (!queryObject)
1654 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001656 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001657 }
1658
1659 // check for type mismatch
1660 if (queryObject->getType() != target)
1661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001662 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001663 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001664 }
1665
1666 return true;
1667}
1668
Corentin Wallezad3ae902018-03-09 13:40:42 -05001669bool ValidateBeginQueryEXT(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670{
1671 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001672 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001675 return false;
1676 }
1677
1678 return ValidateBeginQueryBase(context, target, id);
1679}
1680
Corentin Wallezad3ae902018-03-09 13:40:42 -05001681bool ValidateEndQueryBase(gl::Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001682{
1683 if (!ValidQueryType(context, target))
1684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001685 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001686 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001687 }
1688
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001689 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001690
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001691 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001693 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001694 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001695 }
1696
Jamie Madill45c785d2014-05-13 14:09:34 -04001697 return true;
1698}
1699
Corentin Wallezad3ae902018-03-09 13:40:42 -05001700bool ValidateEndQueryEXT(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001701{
1702 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001703 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001704 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001706 return false;
1707 }
1708
1709 return ValidateEndQueryBase(context, target);
1710}
1711
Corentin Wallezad3ae902018-03-09 13:40:42 -05001712bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713{
1714 if (!context->getExtensions().disjointTimerQuery)
1715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001716 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001717 return false;
1718 }
1719
Corentin Wallezad3ae902018-03-09 13:40:42 -05001720 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001722 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001723 return false;
1724 }
1725
1726 Query *queryObject = context->getQuery(id, true, target);
1727 if (queryObject == nullptr)
1728 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001729 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001730 return false;
1731 }
1732
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001733 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001734 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001735 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736 return false;
1737 }
1738
1739 return true;
1740}
1741
Corentin Wallezad3ae902018-03-09 13:40:42 -05001742bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001743{
Geoff Lang2186c382016-10-14 10:54:54 -04001744 if (numParams)
1745 {
1746 *numParams = 0;
1747 }
1748
Corentin Wallezad3ae902018-03-09 13:40:42 -05001749 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752 return false;
1753 }
1754
1755 switch (pname)
1756 {
1757 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001758 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001760 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001761 return false;
1762 }
1763 break;
1764 case GL_QUERY_COUNTER_BITS_EXT:
1765 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001766 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001768 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769 return false;
1770 }
1771 break;
1772 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001773 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001774 return false;
1775 }
1776
Geoff Lang2186c382016-10-14 10:54:54 -04001777 if (numParams)
1778 {
1779 // All queries return only one value
1780 *numParams = 1;
1781 }
1782
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001783 return true;
1784}
1785
Corentin Wallezad3ae902018-03-09 13:40:42 -05001786bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001787{
1788 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001789 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001790 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001791 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001792 return false;
1793 }
1794
Geoff Lang2186c382016-10-14 10:54:54 -04001795 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001796}
1797
Geoff Lang2186c382016-10-14 10:54:54 -04001798bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001799 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001800 GLenum pname,
1801 GLsizei bufSize,
1802 GLsizei *length,
1803 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001804{
Geoff Lang2186c382016-10-14 10:54:54 -04001805 if (!ValidateRobustEntryPoint(context, bufSize))
1806 {
1807 return false;
1808 }
1809
Brandon Jonesd1049182018-03-28 10:02:20 -07001810 GLsizei numParams = 0;
1811
1812 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001813 {
1814 return false;
1815 }
1816
Brandon Jonesd1049182018-03-28 10:02:20 -07001817 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001818 {
1819 return false;
1820 }
1821
Brandon Jonesd1049182018-03-28 10:02:20 -07001822 SetRobustLengthParam(length, numParams);
1823
Geoff Lang2186c382016-10-14 10:54:54 -04001824 return true;
1825}
1826
1827bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1828{
1829 if (numParams)
1830 {
1831 *numParams = 0;
1832 }
1833
Corentin Wallezad3ae902018-03-09 13:40:42 -05001834 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001835
1836 if (!queryObject)
1837 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001838 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001839 return false;
1840 }
1841
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001842 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001843 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001845 return false;
1846 }
1847
1848 switch (pname)
1849 {
1850 case GL_QUERY_RESULT_EXT:
1851 case GL_QUERY_RESULT_AVAILABLE_EXT:
1852 break;
1853
1854 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001855 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001856 return false;
1857 }
1858
Geoff Lang2186c382016-10-14 10:54:54 -04001859 if (numParams)
1860 {
1861 *numParams = 1;
1862 }
1863
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001864 return true;
1865}
1866
1867bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1868{
1869 if (!context->getExtensions().disjointTimerQuery)
1870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001871 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001872 return false;
1873 }
Geoff Lang2186c382016-10-14 10:54:54 -04001874 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1875}
1876
1877bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1878 GLuint id,
1879 GLenum pname,
1880 GLsizei bufSize,
1881 GLsizei *length,
1882 GLint *params)
1883{
1884 if (!context->getExtensions().disjointTimerQuery)
1885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001886 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001887 return false;
1888 }
1889
1890 if (!ValidateRobustEntryPoint(context, bufSize))
1891 {
1892 return false;
1893 }
1894
Brandon Jonesd1049182018-03-28 10:02:20 -07001895 GLsizei numParams = 0;
1896
1897 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001898 {
1899 return false;
1900 }
1901
Brandon Jonesd1049182018-03-28 10:02:20 -07001902 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001903 {
1904 return false;
1905 }
1906
Brandon Jonesd1049182018-03-28 10:02:20 -07001907 SetRobustLengthParam(length, numParams);
1908
Geoff Lang2186c382016-10-14 10:54:54 -04001909 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001910}
1911
1912bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1913{
1914 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001915 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001917 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001918 return false;
1919 }
Geoff Lang2186c382016-10-14 10:54:54 -04001920 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1921}
1922
1923bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1924 GLuint id,
1925 GLenum pname,
1926 GLsizei bufSize,
1927 GLsizei *length,
1928 GLuint *params)
1929{
1930 if (!context->getExtensions().disjointTimerQuery &&
1931 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1932 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001934 return false;
1935 }
1936
1937 if (!ValidateRobustEntryPoint(context, bufSize))
1938 {
1939 return false;
1940 }
1941
Brandon Jonesd1049182018-03-28 10:02:20 -07001942 GLsizei numParams = 0;
1943
1944 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001945 {
1946 return false;
1947 }
1948
Brandon Jonesd1049182018-03-28 10:02:20 -07001949 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001950 {
1951 return false;
1952 }
1953
Brandon Jonesd1049182018-03-28 10:02:20 -07001954 SetRobustLengthParam(length, numParams);
1955
Geoff Lang2186c382016-10-14 10:54:54 -04001956 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001957}
1958
1959bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1960{
1961 if (!context->getExtensions().disjointTimerQuery)
1962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001963 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001964 return false;
1965 }
Geoff Lang2186c382016-10-14 10:54:54 -04001966 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1967}
1968
1969bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1970 GLuint id,
1971 GLenum pname,
1972 GLsizei bufSize,
1973 GLsizei *length,
1974 GLint64 *params)
1975{
1976 if (!context->getExtensions().disjointTimerQuery)
1977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001978 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001979 return false;
1980 }
1981
1982 if (!ValidateRobustEntryPoint(context, bufSize))
1983 {
1984 return false;
1985 }
1986
Brandon Jonesd1049182018-03-28 10:02:20 -07001987 GLsizei numParams = 0;
1988
1989 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001990 {
1991 return false;
1992 }
1993
Brandon Jonesd1049182018-03-28 10:02:20 -07001994 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001995 {
1996 return false;
1997 }
1998
Brandon Jonesd1049182018-03-28 10:02:20 -07001999 SetRobustLengthParam(length, numParams);
2000
Geoff Lang2186c382016-10-14 10:54:54 -04002001 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002002}
2003
2004bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2005{
2006 if (!context->getExtensions().disjointTimerQuery)
2007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002008 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002009 return false;
2010 }
Geoff Lang2186c382016-10-14 10:54:54 -04002011 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2012}
2013
2014bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2015 GLuint id,
2016 GLenum pname,
2017 GLsizei bufSize,
2018 GLsizei *length,
2019 GLuint64 *params)
2020{
2021 if (!context->getExtensions().disjointTimerQuery)
2022 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002023 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002024 return false;
2025 }
2026
2027 if (!ValidateRobustEntryPoint(context, bufSize))
2028 {
2029 return false;
2030 }
2031
Brandon Jonesd1049182018-03-28 10:02:20 -07002032 GLsizei numParams = 0;
2033
2034 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002035 {
2036 return false;
2037 }
2038
Brandon Jonesd1049182018-03-28 10:02:20 -07002039 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002040 {
2041 return false;
2042 }
2043
Brandon Jonesd1049182018-03-28 10:02:20 -07002044 SetRobustLengthParam(length, numParams);
2045
Geoff Lang2186c382016-10-14 10:54:54 -04002046 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002047}
2048
Jamie Madill5b772312018-03-08 20:28:32 -05002049bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002050 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002051 GLint location,
2052 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002053 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002054{
Jiajia Qin5451d532017-11-16 17:16:34 +08002055 // TODO(Jiajia): Add image uniform check in future.
2056 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002057 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002058 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002059 return false;
2060 }
2061
Jiajia Qin5451d532017-11-16 17:16:34 +08002062 if (!program)
2063 {
2064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2065 return false;
2066 }
2067
2068 if (!program->isLinked())
2069 {
2070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2071 return false;
2072 }
2073
2074 if (location == -1)
2075 {
2076 // Silently ignore the uniform command
2077 return false;
2078 }
2079
2080 const auto &uniformLocations = program->getUniformLocations();
2081 size_t castedLocation = static_cast<size_t>(location);
2082 if (castedLocation >= uniformLocations.size())
2083 {
2084 context->handleError(InvalidOperation() << "Invalid uniform location");
2085 return false;
2086 }
2087
2088 const auto &uniformLocation = uniformLocations[castedLocation];
2089 if (uniformLocation.ignored)
2090 {
2091 // Silently ignore the uniform command
2092 return false;
2093 }
2094
2095 if (!uniformLocation.used())
2096 {
2097 context->handleError(InvalidOperation());
2098 return false;
2099 }
2100
2101 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2102
2103 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002104 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002105 {
2106 context->handleError(InvalidOperation());
2107 return false;
2108 }
2109
2110 *uniformOut = &uniform;
2111 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002112}
2113
Jamie Madill5b772312018-03-08 20:28:32 -05002114bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002115 GLenum uniformType,
2116 GLsizei count,
2117 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002118{
Jiajia Qin5451d532017-11-16 17:16:34 +08002119 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2120 // It is compatible with INT or BOOL.
2121 // Do these cheap tests first, for a little extra speed.
2122 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002123 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002124 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002125 }
2126
Jiajia Qin5451d532017-11-16 17:16:34 +08002127 if (IsSamplerType(uniformType))
2128 {
2129 // Check that the values are in range.
2130 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2131 for (GLsizei i = 0; i < count; ++i)
2132 {
2133 if (value[i] < 0 || value[i] >= max)
2134 {
2135 context->handleError(InvalidValue() << "sampler uniform value out of range");
2136 return false;
2137 }
2138 }
2139 return true;
2140 }
2141
2142 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2143 return false;
2144}
2145
Jamie Madill5b772312018-03-08 20:28:32 -05002146bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002147{
2148 // Check that the value type is compatible with uniform type.
2149 // Do the cheaper test first, for a little extra speed.
2150 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2151 {
2152 return true;
2153 }
2154
2155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2156 return false;
2157}
2158
Jamie Madill5b772312018-03-08 20:28:32 -05002159bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002160{
2161 // Check that the value type is compatible with uniform type.
2162 if (valueType == uniformType)
2163 {
2164 return true;
2165 }
2166
2167 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2168 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002169}
2170
Jamie Madill5b772312018-03-08 20:28:32 -05002171bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002172{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002173 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002174 gl::Program *programObject = context->getGLState().getProgram();
2175 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2176 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002177}
2178
Jamie Madill5b772312018-03-08 20:28:32 -05002179bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002180{
2181 const LinkedUniform *uniform = nullptr;
2182 gl::Program *programObject = context->getGLState().getProgram();
2183 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2184 ValidateUniform1ivValue(context, uniform->type, count, value);
2185}
2186
Jamie Madill5b772312018-03-08 20:28:32 -05002187bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002188 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002189 GLint location,
2190 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002191 GLboolean transpose)
2192{
Geoff Lang92019432017-11-20 13:09:34 -05002193 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002195 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002196 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002197 }
2198
Jamie Madill62d31cb2015-09-11 13:25:51 -04002199 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002200 gl::Program *programObject = context->getGLState().getProgram();
2201 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2202 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002203}
2204
Jamie Madill5b772312018-03-08 20:28:32 -05002205bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002206{
2207 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002209 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002210 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002211 }
2212
Jamie Madill0af26e12015-03-05 19:54:33 -05002213 const Caps &caps = context->getCaps();
2214
Jamie Madill893ab082014-05-16 16:56:10 -04002215 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2216 {
2217 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2218
Jamie Madill0af26e12015-03-05 19:54:33 -05002219 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002221 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002222 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002223 }
2224 }
2225
2226 switch (pname)
2227 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002228 case GL_TEXTURE_BINDING_2D:
2229 case GL_TEXTURE_BINDING_CUBE_MAP:
2230 case GL_TEXTURE_BINDING_3D:
2231 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002232 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002233 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002234 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2235 if (!context->getExtensions().textureRectangle)
2236 {
2237 context->handleError(InvalidEnum()
2238 << "ANGLE_texture_rectangle extension not present");
2239 return false;
2240 }
2241 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002242 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2243 if (!context->getExtensions().eglStreamConsumerExternal &&
2244 !context->getExtensions().eglImageExternal)
2245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002246 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2247 "nor GL_OES_EGL_image_external "
2248 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002249 return false;
2250 }
2251 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002252
He Yunchaoced53ae2016-11-29 15:00:51 +08002253 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2254 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002255 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002256 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2257 ASSERT(readFramebuffer);
2258
Jamie Madill427064d2018-04-13 16:20:34 -04002259 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002260 {
Geoff Langb1196682014-07-23 13:47:29 -04002261 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002262 }
2263
Jamie Madille98b1b52018-03-08 09:47:23 -05002264 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002265 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002266 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002267 return false;
2268 }
2269
Jamie Madille98b1b52018-03-08 09:47:23 -05002270 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002271 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002273 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002274 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002275 }
2276 }
2277 break;
2278
He Yunchaoced53ae2016-11-29 15:00:51 +08002279 default:
2280 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002281 }
2282
2283 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002284 if (*numParams == 0)
2285 {
2286 return false;
2287 }
2288
2289 return true;
2290}
2291
Brandon Jonesd1049182018-03-28 10:02:20 -07002292bool ValidateGetBooleanvRobustANGLE(Context *context,
2293 GLenum pname,
2294 GLsizei bufSize,
2295 GLsizei *length,
2296 GLboolean *params)
2297{
2298 GLenum nativeType;
2299 unsigned int numParams = 0;
2300
2301 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2302 {
2303 return false;
2304 }
2305
2306 SetRobustLengthParam(length, numParams);
2307
2308 return true;
2309}
2310
2311bool ValidateGetFloatvRobustANGLE(Context *context,
2312 GLenum pname,
2313 GLsizei bufSize,
2314 GLsizei *length,
2315 GLfloat *params)
2316{
2317 GLenum nativeType;
2318 unsigned int numParams = 0;
2319
2320 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2321 {
2322 return false;
2323 }
2324
2325 SetRobustLengthParam(length, numParams);
2326
2327 return true;
2328}
2329
2330bool ValidateGetIntegervRobustANGLE(Context *context,
2331 GLenum pname,
2332 GLsizei bufSize,
2333 GLsizei *length,
2334 GLint *data)
2335{
2336 GLenum nativeType;
2337 unsigned int numParams = 0;
2338
2339 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2340 {
2341 return false;
2342 }
2343
2344 SetRobustLengthParam(length, numParams);
2345
2346 return true;
2347}
2348
2349bool ValidateGetInteger64vRobustANGLE(Context *context,
2350 GLenum pname,
2351 GLsizei bufSize,
2352 GLsizei *length,
2353 GLint64 *data)
2354{
2355 GLenum nativeType;
2356 unsigned int numParams = 0;
2357
2358 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2359 {
2360 return false;
2361 }
2362
2363 if (nativeType == GL_INT_64_ANGLEX)
2364 {
2365 CastStateValues(context, nativeType, pname, numParams, data);
2366 return false;
2367 }
2368
2369 SetRobustLengthParam(length, numParams);
2370 return true;
2371}
2372
Jamie Madill5b772312018-03-08 20:28:32 -05002373bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002374 GLenum pname,
2375 GLsizei bufSize,
2376 GLenum *nativeType,
2377 unsigned int *numParams)
2378{
2379 if (!ValidateRobustEntryPoint(context, bufSize))
2380 {
2381 return false;
2382 }
2383
2384 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2385 {
2386 return false;
2387 }
2388
2389 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002390 {
2391 return false;
2392 }
2393
2394 return true;
2395}
2396
Jamie Madill5b772312018-03-08 20:28:32 -05002397bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002398 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002399 GLint level,
2400 GLenum internalformat,
2401 bool isSubImage,
2402 GLint xoffset,
2403 GLint yoffset,
2404 GLint zoffset,
2405 GLint x,
2406 GLint y,
2407 GLsizei width,
2408 GLsizei height,
2409 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002410 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002411{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002412 TextureType texType = TextureTargetToType(target);
2413
Brandon Jones6cad5662017-06-14 13:25:13 -07002414 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002415 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002416 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2417 return false;
2418 }
2419
2420 if (width < 0 || height < 0)
2421 {
2422 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002423 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 }
2425
He Yunchaoced53ae2016-11-29 15:00:51 +08002426 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2427 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002429 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002430 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002431 }
2432
2433 if (border != 0)
2434 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002435 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002436 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002437 }
2438
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002439 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002440 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002441 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002442 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002443 }
2444
Jamie Madille98b1b52018-03-08 09:47:23 -05002445 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002446 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002447 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002448 {
Geoff Langb1196682014-07-23 13:47:29 -04002449 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002450 }
2451
Jamie Madille98b1b52018-03-08 09:47:23 -05002452 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002453 {
Geoff Langb1196682014-07-23 13:47:29 -04002454 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002455 }
2456
Martin Radev138064f2016-07-15 12:03:41 +03002457 if (readFramebuffer->getReadBufferState() == GL_NONE)
2458 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002460 return false;
2461 }
2462
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002463 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2464 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002465 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002466 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002467 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2468 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002470 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002471 return false;
2472 }
2473
Martin Radev04e2c3b2017-07-27 16:54:35 +03002474 // ANGLE_multiview spec, Revision 1:
2475 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2476 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002477 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2478 // framebuffer is more than one.
2479 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002480 {
2481 context->handleError(InvalidFramebufferOperation()
2482 << "The active read framebuffer object has multiview attachments.");
2483 return false;
2484 }
2485
Geoff Langaae65a42014-05-26 12:43:44 -04002486 const gl::Caps &caps = context->getCaps();
2487
Geoff Langaae65a42014-05-26 12:43:44 -04002488 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002489 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002491 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002492 maxDimension = caps.max2DTextureSize;
2493 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002494
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002495 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002496 maxDimension = caps.maxCubeMapTextureSize;
2497 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002498
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002499 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002500 maxDimension = caps.maxRectangleTextureSize;
2501 break;
2502
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002503 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002504 maxDimension = caps.max2DTextureSize;
2505 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002506
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002507 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002508 maxDimension = caps.max3DTextureSize;
2509 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002510
He Yunchaoced53ae2016-11-29 15:00:51 +08002511 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002512 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002513 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002514 }
2515
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002516 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002517 if (!texture)
2518 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002519 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002520 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002521 }
2522
Geoff Lang69cce582015-09-17 13:20:36 -04002523 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002525 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002526 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002527 }
2528
Geoff Langca271392017-04-05 12:30:00 -04002529 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002530 isSubImage ? *texture->getFormat(target, level).info
2531 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002532
Geoff Lang966c9402017-04-18 12:38:27 -04002533 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002535 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002536 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002537 }
2538
2539 if (isSubImage)
2540 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002541 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2542 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2543 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002545 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002546 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002547 }
2548 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002549 else
2550 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002551 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002552 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002553 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002554 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002555 }
2556
Geoff Langeb66a6e2016-10-31 13:06:12 -04002557 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002558 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002559 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002560 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002561 }
2562
2563 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002564 if (static_cast<int>(width) > maxLevelDimension ||
2565 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002566 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002567 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002568 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002569 }
2570 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002571
Jamie Madill0c8abca2016-07-22 20:21:26 -04002572 if (textureFormatOut)
2573 {
2574 *textureFormatOut = texture->getFormat(target, level);
2575 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002576
2577 // Detect texture copying feedback loops for WebGL.
2578 if (context->getExtensions().webglCompatibility)
2579 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002580 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002581 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002582 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002583 return false;
2584 }
2585 }
2586
Jamie Madill560a8d82014-05-21 13:06:20 -04002587 return true;
2588}
2589
Jamie Madill493f9572018-05-24 19:52:15 -04002590bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002591{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002592 const Extensions &extensions = context->getExtensions();
2593
Jamie Madill1aeb1312014-06-20 13:21:25 -04002594 switch (mode)
2595 {
Jamie Madill493f9572018-05-24 19:52:15 -04002596 case PrimitiveMode::Points:
2597 case PrimitiveMode::Lines:
2598 case PrimitiveMode::LineLoop:
2599 case PrimitiveMode::LineStrip:
2600 case PrimitiveMode::Triangles:
2601 case PrimitiveMode::TriangleStrip:
2602 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002603 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002604
Jamie Madill493f9572018-05-24 19:52:15 -04002605 case PrimitiveMode::LinesAdjacency:
2606 case PrimitiveMode::LineStripAdjacency:
2607 case PrimitiveMode::TrianglesAdjacency:
2608 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002609 if (!extensions.geometryShader)
2610 {
2611 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2612 return false;
2613 }
2614 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002615 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002616 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002617 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002618 }
2619
Jamie Madill250d33f2014-06-06 17:09:03 -04002620 if (count < 0)
2621 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002622 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002623 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002624 }
2625
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002626 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002627
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002628 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2629 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2630 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2631 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002632 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002633 // Check for mapped buffers
2634 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002635 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002636 {
2637 context->handleError(InvalidOperation());
2638 return false;
2639 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002640 }
2641
Jamie Madillcbcde722017-01-06 14:50:00 -05002642 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2643 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002644 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002645 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002646 {
Ken Russellb9f92502018-01-27 19:00:26 -08002647 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002648 const FramebufferAttachment *dsAttachment =
2649 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002650 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2651 ASSERT(stencilBits <= 8);
2652
Jinyoung Hur85769f02015-10-20 17:08:44 -04002653 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002654 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002655 {
Ken Russellb9f92502018-01-27 19:00:26 -08002656 GLuint maxStencilValue = (1 << stencilBits) - 1;
2657
2658 bool differentRefs =
2659 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2660 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2661 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2662 (depthStencilState.stencilBackWritemask & maxStencilValue);
2663 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2664 (depthStencilState.stencilBackMask & maxStencilValue);
2665
2666 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002667 {
Ken Russellb9f92502018-01-27 19:00:26 -08002668 if (!extensions.webglCompatibility)
2669 {
Jamie Madilla2f043d2018-07-10 17:21:20 -04002670 WARN() << "This ANGLE implementation does not support separate front/back "
2671 "stencil writemasks, reference values, or stencil mask values.";
Ken Russellb9f92502018-01-27 19:00:26 -08002672 }
2673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2674 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002675 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002676 }
Jamie Madillac528012014-06-20 13:21:23 -04002677 }
2678
Jamie Madill427064d2018-04-13 16:20:34 -04002679 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002680 {
Geoff Langb1196682014-07-23 13:47:29 -04002681 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002682 }
2683
Jamie Madill2da53562018-08-01 11:34:47 -04002684 if (context->getStateCache().hasAnyEnabledClientAttrib())
2685 {
2686 if (!ValidateDrawClientAttribs(context))
2687 {
2688 return false;
2689 }
2690 }
2691
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002692 // If we are running GLES1, there is no current program.
2693 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002694 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002695
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002696 gl::Program *program = state.getProgram();
2697 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002698 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002700 return false;
2701 }
Martin Radev7e69f762017-07-27 14:54:13 +03002702
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002703 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2704 // vertex shader stage or fragment shader stage is a undefined behaviour.
2705 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2706 // produce undefined result.
2707 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2708 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002709 {
2710 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002711 << "It is a undefined behaviour to render without "
2712 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002713 return false;
2714 }
Martin Radevffe754b2017-07-31 10:38:07 +03002715
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002716 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002717 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002718 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002719 return false;
2720 }
2721
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002722 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002723 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002724 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2725 const int framebufferNumViews = framebuffer->getNumViews();
2726 if (framebufferNumViews != programNumViews)
2727 {
2728 context->handleError(InvalidOperation()
2729 << "The number of views in the active program "
2730 "and draw framebuffer does not match.");
2731 return false;
2732 }
2733
2734 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2735 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2736 framebufferNumViews > 1)
2737 {
2738 context->handleError(InvalidOperation()
2739 << "There is an active transform feedback object "
2740 "when the number of views in the active draw "
2741 "framebuffer is greater than 1.");
2742 return false;
2743 }
2744
2745 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2746 state.isQueryActive(QueryType::TimeElapsed))
2747 {
2748 context->handleError(InvalidOperation()
2749 << "There is an active query for target "
2750 "GL_TIME_ELAPSED_EXT when the number of "
2751 "views in the active draw framebuffer is "
2752 "greater than 1.");
2753 return false;
2754 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002755 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002756
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002757 // Do geometry shader specific validations
2758 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002759 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002760 if (!IsCompatibleDrawModeWithGeometryShader(
2761 mode, program->getGeometryShaderInputPrimitiveType()))
2762 {
2763 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2764 IncompatibleDrawModeAgainstGeometryShader);
2765 return false;
2766 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002767 }
Geoff Lange0cff192017-05-30 13:04:56 -04002768
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002769 // Uniform buffer validation
2770 for (unsigned int uniformBlockIndex = 0;
2771 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002772 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002773 const gl::InterfaceBlock &uniformBlock =
2774 program->getUniformBlockByIndex(uniformBlockIndex);
2775 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2776 const OffsetBindingPointer<Buffer> &uniformBuffer =
2777 state.getIndexedUniformBuffer(blockBinding);
2778
2779 if (uniformBuffer.get() == nullptr)
2780 {
2781 // undefined behaviour
2782 context->handleError(
2783 InvalidOperation()
2784 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2785 return false;
2786 }
2787
2788 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2789 if (uniformBufferSize < uniformBlock.dataSize)
2790 {
2791 // undefined behaviour
2792 context->handleError(
2793 InvalidOperation()
2794 << "It is undefined behaviour to use a uniform buffer that is too small.");
2795 return false;
2796 }
2797
2798 if (extensions.webglCompatibility &&
2799 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2800 {
2801 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2802 UniformBufferBoundForTransformFeedback);
2803 return false;
2804 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002805 }
2806
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002807 // Do some additonal WebGL-specific validation
2808 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002809 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002810 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2811 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2812 transformFeedbackObject->buffersBoundForOtherUse())
2813 {
2814 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2815 TransformFeedbackBufferDoubleBound);
2816 return false;
2817 }
2818 // Detect rendering feedback loops for WebGL.
2819 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2820 {
2821 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2822 return false;
2823 }
2824
2825 // Detect that the vertex shader input types match the attribute types
2826 if (!ValidateVertexShaderAttributeTypeMatch(context))
2827 {
2828 return false;
2829 }
2830
2831 // Detect that the color buffer types match the fragment shader output types
2832 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2833 {
2834 return false;
2835 }
Jamie Madillac43aaa2018-07-31 11:22:13 -04002836
2837 if (count > 0)
2838 {
2839 const VertexArray *vao = context->getGLState().getVertexArray();
2840 if (vao->hasTransformFeedbackBindingConflict(context))
2841 {
2842 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2843 VertexBufferBoundForTransformFeedback);
2844 return false;
2845 }
2846 }
Geoff Lange0cff192017-05-30 13:04:56 -04002847 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002848 }
2849
Jamie Madill9fdaa492018-02-16 10:52:11 -05002850 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002851}
2852
Jamie Madill5b772312018-03-08 20:28:32 -05002853bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002854 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002855 GLint first,
2856 GLsizei count,
2857 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002858{
Jamie Madillfd716582014-06-06 17:09:04 -04002859 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002860 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002861 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002862 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002863 }
2864
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002865 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002866 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002867 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002868 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002869 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002870 if (!ValidateTransformFeedbackPrimitiveMode(context,
2871 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002872 {
James Darpinian30b604d2018-03-12 17:26:57 -07002873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2874 return false;
2875 }
2876
2877 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2878 {
2879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2880 return false;
2881 }
Jamie Madillfd716582014-06-06 17:09:04 -04002882 }
2883
Jiajia Qind9671222016-11-29 16:30:31 +08002884 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002885 {
2886 return false;
2887 }
2888
Corentin Wallez71168a02016-12-19 15:11:18 -08002889 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002890 // - first < 0 has been checked as an error condition.
2891 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002892 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002893 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002894 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002895 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002896 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2897 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2898 {
2899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2900 return false;
2901 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002902
Jamie Madill2da53562018-08-01 11:34:47 -04002903 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002904 {
2905 return false;
2906 }
Jamie Madillfd716582014-06-06 17:09:04 -04002907 }
2908
2909 return true;
2910}
2911
He Yunchaoced53ae2016-11-29 15:00:51 +08002912bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002913 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002914 GLint first,
2915 GLsizei count,
2916 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002917{
Geoff Lang63c5a592017-09-27 14:08:16 -04002918 if (!context->getExtensions().instancedArrays)
2919 {
2920 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2921 return false;
2922 }
2923
Corentin Wallez170efbf2017-05-02 13:45:01 -04002924 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002925 {
2926 return false;
2927 }
2928
Corentin Wallez0dc97812017-06-22 14:38:44 -04002929 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002930}
2931
Jamie Madill493f9572018-05-24 19:52:15 -04002932bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002933{
Jamie Madill250d33f2014-06-06 17:09:03 -04002934 switch (type)
2935 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002936 case GL_UNSIGNED_BYTE:
2937 case GL_UNSIGNED_SHORT:
2938 break;
2939 case GL_UNSIGNED_INT:
2940 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002942 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002943 return false;
2944 }
2945 break;
2946 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002947 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002948 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002949 }
2950
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002951 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002952
2953 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002954 if (curTransformFeedback && curTransformFeedback->isActive() &&
2955 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002956 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002957 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2958 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2959 if (context->getExtensions().geometryShader)
2960 {
2961 if (!ValidateTransformFeedbackPrimitiveMode(
2962 context, curTransformFeedback->getPrimitiveMode(), mode))
2963 {
2964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2965 return false;
2966 }
2967 }
2968 else
2969 {
2970 // It is an invalid operation to call DrawElements, DrawRangeElements or
2971 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2972 // 86)
2973 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2974 UnsupportedDrawModeForTransformFeedback);
2975 return false;
2976 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002977 }
2978
Jiajia Qind9671222016-11-29 16:30:31 +08002979 return true;
2980}
2981
Jamie Madill5b772312018-03-08 20:28:32 -05002982bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002983 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002984 GLsizei count,
2985 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002986 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002987 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002988{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002989 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08002990 return false;
2991
2992 const State &state = context->getGLState();
2993
Corentin Wallez170efbf2017-05-02 13:45:01 -04002994 if (!ValidateDrawBase(context, mode, count))
2995 {
2996 return false;
2997 }
2998
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002999 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
3000 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3001 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3002 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04003003 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003004 // Check for mapped buffers
3005 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04003006 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003007 {
3008 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3009 return false;
3010 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003011 }
3012
He Yunchaoced53ae2016-11-29 15:00:51 +08003013 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003014 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003015
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003016 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3017
3018 if (context->getExtensions().webglCompatibility)
3019 {
3020 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3021 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3022 {
3023 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3024 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3025 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003026 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003027 return false;
3028 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003029
3030 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3031 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3032 // error is generated.
3033 if (reinterpret_cast<intptr_t>(indices) < 0)
3034 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003035 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003036 return false;
3037 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003038 }
3039
3040 if (context->getExtensions().webglCompatibility ||
3041 !context->getGLState().areClientArraysEnabled())
3042 {
Brandon Jones2a018152018-06-08 15:59:26 -07003043 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003044 {
3045 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003046 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3047 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003048 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003049 return false;
3050 }
3051 }
3052
Jamie Madill9fdaa492018-02-16 10:52:11 -05003053 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003054 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003055 // This is an application error that would normally result in a crash, but we catch it and
3056 // return an error
3057 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3058 return false;
3059 }
3060
3061 if (count > 0 && elementArrayBuffer)
3062 {
3063 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3064 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3065 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3066 constexpr uint64_t kMaxTypeSize = 8;
3067 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3068 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3069 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3070
3071 uint64_t typeSize = typeBytes;
3072 uint64_t elementCount = static_cast<uint64_t>(count);
3073 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3074
3075 // Doing the multiplication here is overflow-safe
3076 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3077
3078 // The offset can be any value, check for overflows
3079 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3080 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003081 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3083 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003084 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003085
3086 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3087 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003088 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3090 return false;
3091 }
3092
3093 ASSERT(isPow2(typeSize) && typeSize > 0);
3094 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3095 {
3096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003097 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003098 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003099
3100 if (context->getExtensions().webglCompatibility &&
3101 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3102 {
3103 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3104 ElementArrayBufferBoundForTransformFeedback);
3105 return false;
3106 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003107 }
3108
Jamie Madill2da53562018-08-01 11:34:47 -04003109 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003110 {
3111 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003112 const DrawCallParams &params = context->getParams<DrawCallParams>();
3113 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3114 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003115
3116 // If we use an index greater than our maximum supported index range, return an error.
3117 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3118 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003119 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003120 {
3121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3122 return false;
3123 }
3124
Jamie Madill2da53562018-08-01 11:34:47 -04003125 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003126 {
3127 return false;
3128 }
3129
3130 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003131 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003132 }
3133
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003134 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003135}
3136
Jamie Madill5b772312018-03-08 20:28:32 -05003137bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003138 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003139 GLsizei count,
3140 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003141 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003142 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003143{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003144 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003145}
3146
Geoff Lang3edfe032015-09-04 16:38:24 -04003147bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003148 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003149 GLsizei count,
3150 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003151 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003152 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003153{
Geoff Lang63c5a592017-09-27 14:08:16 -04003154 if (!context->getExtensions().instancedArrays)
3155 {
3156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3157 return false;
3158 }
3159
Corentin Wallez170efbf2017-05-02 13:45:01 -04003160 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003161 {
3162 return false;
3163 }
3164
Corentin Wallez0dc97812017-06-22 14:38:44 -04003165 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003166}
3167
He Yunchaoced53ae2016-11-29 15:00:51 +08003168bool ValidateFramebufferTextureBase(Context *context,
3169 GLenum target,
3170 GLenum attachment,
3171 GLuint texture,
3172 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003173{
Geoff Lange8afa902017-09-27 15:00:43 -04003174 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003177 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003178 }
3179
3180 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003181 {
3182 return false;
3183 }
3184
Jamie Madill55ec3b12014-07-03 10:38:57 -04003185 if (texture != 0)
3186 {
3187 gl::Texture *tex = context->getTexture(texture);
3188
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003189 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003191 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003192 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003193 }
3194
3195 if (level < 0)
3196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003197 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003198 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003199 }
3200 }
3201
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003202 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003203 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003204
Jamie Madill84115c92015-04-23 15:00:07 -04003205 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003206 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003207 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003208 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003209 }
3210
3211 return true;
3212}
3213
Geoff Langb1196682014-07-23 13:47:29 -04003214bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003215{
3216 if (program == 0)
3217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003218 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003219 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003220 }
3221
Dian Xiang769769a2015-09-09 15:20:08 -07003222 gl::Program *programObject = GetValidProgram(context, program);
3223 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003224 {
3225 return false;
3226 }
3227
Jamie Madill0063c512014-08-25 15:47:53 -04003228 if (!programObject || !programObject->isLinked())
3229 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003231 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003232 }
3233
Geoff Lang7dd2e102014-11-10 15:19:26 -05003234 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003236 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003237 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003238 }
3239
Jamie Madill0063c512014-08-25 15:47:53 -04003240 return true;
3241}
3242
Geoff Langf41d0ee2016-10-07 13:04:23 -04003243static bool ValidateSizedGetUniform(Context *context,
3244 GLuint program,
3245 GLint location,
3246 GLsizei bufSize,
3247 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003248{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003249 if (length)
3250 {
3251 *length = 0;
3252 }
3253
Jamie Madill78f41802014-08-25 15:47:55 -04003254 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003255 {
Jamie Madill78f41802014-08-25 15:47:55 -04003256 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003257 }
3258
Geoff Langf41d0ee2016-10-07 13:04:23 -04003259 if (bufSize < 0)
3260 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003261 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003262 return false;
3263 }
3264
Jamie Madilla502c742014-08-28 17:19:13 -04003265 gl::Program *programObject = context->getProgram(program);
3266 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003267
Jamie Madill78f41802014-08-25 15:47:55 -04003268 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003269 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003270 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003271 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003272 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003274 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003275 }
3276
Geoff Langf41d0ee2016-10-07 13:04:23 -04003277 if (length)
3278 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003279 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003280 }
3281
Jamie Madill0063c512014-08-25 15:47:53 -04003282 return true;
3283}
3284
He Yunchaoced53ae2016-11-29 15:00:51 +08003285bool ValidateGetnUniformfvEXT(Context *context,
3286 GLuint program,
3287 GLint location,
3288 GLsizei bufSize,
3289 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003290{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003291 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003292}
3293
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003294bool ValidateGetnUniformfvRobustANGLE(Context *context,
3295 GLuint program,
3296 GLint location,
3297 GLsizei bufSize,
3298 GLsizei *length,
3299 GLfloat *params)
3300{
3301 UNIMPLEMENTED();
3302 return false;
3303}
3304
He Yunchaoced53ae2016-11-29 15:00:51 +08003305bool ValidateGetnUniformivEXT(Context *context,
3306 GLuint program,
3307 GLint location,
3308 GLsizei bufSize,
3309 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003310{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003311 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3312}
3313
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003314bool ValidateGetnUniformivRobustANGLE(Context *context,
3315 GLuint program,
3316 GLint location,
3317 GLsizei bufSize,
3318 GLsizei *length,
3319 GLint *params)
3320{
3321 UNIMPLEMENTED();
3322 return false;
3323}
3324
3325bool ValidateGetnUniformuivRobustANGLE(Context *context,
3326 GLuint program,
3327 GLint location,
3328 GLsizei bufSize,
3329 GLsizei *length,
3330 GLuint *params)
3331{
3332 UNIMPLEMENTED();
3333 return false;
3334}
3335
Geoff Langf41d0ee2016-10-07 13:04:23 -04003336bool ValidateGetUniformfvRobustANGLE(Context *context,
3337 GLuint program,
3338 GLint location,
3339 GLsizei bufSize,
3340 GLsizei *length,
3341 GLfloat *params)
3342{
3343 if (!ValidateRobustEntryPoint(context, bufSize))
3344 {
3345 return false;
3346 }
3347
Brandon Jonesd1049182018-03-28 10:02:20 -07003348 GLsizei writeLength = 0;
3349
Geoff Langf41d0ee2016-10-07 13:04:23 -04003350 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003351 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3352 {
3353 return false;
3354 }
3355
3356 SetRobustLengthParam(length, writeLength);
3357
3358 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003359}
3360
3361bool ValidateGetUniformivRobustANGLE(Context *context,
3362 GLuint program,
3363 GLint location,
3364 GLsizei bufSize,
3365 GLsizei *length,
3366 GLint *params)
3367{
3368 if (!ValidateRobustEntryPoint(context, bufSize))
3369 {
3370 return false;
3371 }
3372
Brandon Jonesd1049182018-03-28 10:02:20 -07003373 GLsizei writeLength = 0;
3374
Geoff Langf41d0ee2016-10-07 13:04:23 -04003375 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003376 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3377 {
3378 return false;
3379 }
3380
3381 SetRobustLengthParam(length, writeLength);
3382
3383 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003384}
3385
3386bool ValidateGetUniformuivRobustANGLE(Context *context,
3387 GLuint program,
3388 GLint location,
3389 GLsizei bufSize,
3390 GLsizei *length,
3391 GLuint *params)
3392{
3393 if (!ValidateRobustEntryPoint(context, bufSize))
3394 {
3395 return false;
3396 }
3397
3398 if (context->getClientMajorVersion() < 3)
3399 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003400 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003401 return false;
3402 }
3403
Brandon Jonesd1049182018-03-28 10:02:20 -07003404 GLsizei writeLength = 0;
3405
Geoff Langf41d0ee2016-10-07 13:04:23 -04003406 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003407 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3408 {
3409 return false;
3410 }
3411
3412 SetRobustLengthParam(length, writeLength);
3413
3414 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003415}
3416
He Yunchaoced53ae2016-11-29 15:00:51 +08003417bool ValidateDiscardFramebufferBase(Context *context,
3418 GLenum target,
3419 GLsizei numAttachments,
3420 const GLenum *attachments,
3421 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003422{
3423 if (numAttachments < 0)
3424 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003425 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003426 return false;
3427 }
3428
3429 for (GLsizei i = 0; i < numAttachments; ++i)
3430 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003431 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003432 {
3433 if (defaultFramebuffer)
3434 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003436 return false;
3437 }
3438
3439 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003441 context->handleError(InvalidOperation() << "Requested color attachment is "
3442 "greater than the maximum supported "
3443 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003444 return false;
3445 }
3446 }
3447 else
3448 {
3449 switch (attachments[i])
3450 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003451 case GL_DEPTH_ATTACHMENT:
3452 case GL_STENCIL_ATTACHMENT:
3453 case GL_DEPTH_STENCIL_ATTACHMENT:
3454 if (defaultFramebuffer)
3455 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003456 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3457 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003458 return false;
3459 }
3460 break;
3461 case GL_COLOR:
3462 case GL_DEPTH:
3463 case GL_STENCIL:
3464 if (!defaultFramebuffer)
3465 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003466 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3467 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003468 return false;
3469 }
3470 break;
3471 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003472 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003473 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003474 }
3475 }
3476 }
3477
3478 return true;
3479}
3480
Austin Kinross6ee1e782015-05-29 17:05:37 -07003481bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3482{
Jamie Madill007530e2017-12-28 14:27:04 -05003483 if (!context->getExtensions().debugMarker)
3484 {
3485 // The debug marker calls should not set error state
3486 // However, it seems reasonable to set an error state if the extension is not enabled
3487 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3488 return false;
3489 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003490
Jamie Madill007530e2017-12-28 14:27:04 -05003491 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003492 if (length < 0)
3493 {
3494 return false;
3495 }
3496
3497 if (marker == nullptr)
3498 {
3499 return false;
3500 }
3501
3502 return true;
3503}
3504
3505bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3506{
Jamie Madill007530e2017-12-28 14:27:04 -05003507 if (!context->getExtensions().debugMarker)
3508 {
3509 // The debug marker calls should not set error state
3510 // However, it seems reasonable to set an error state if the extension is not enabled
3511 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3512 return false;
3513 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003514
Jamie Madill007530e2017-12-28 14:27:04 -05003515 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003516 if (length < 0)
3517 {
3518 return false;
3519 }
3520
3521 if (length > 0 && marker == nullptr)
3522 {
3523 return false;
3524 }
3525
3526 return true;
3527}
3528
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003529bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003530{
Geoff Langa8406172015-07-21 16:53:39 -04003531 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003533 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003534 return false;
3535 }
3536
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003537 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003538 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003539 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003540 if (!context->getExtensions().eglImage)
3541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003542 context->handleError(InvalidEnum()
3543 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003544 }
3545 break;
3546
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003547 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003548 if (!context->getExtensions().eglImageExternal)
3549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003550 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3551 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003552 }
Geoff Langa8406172015-07-21 16:53:39 -04003553 break;
3554
3555 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003556 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003557 return false;
3558 }
3559
Rafael Cintron05a449a2018-06-20 18:08:04 -07003560 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003561
Jamie Madill61e16b42017-06-19 11:13:23 -04003562 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003563 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003565 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003566 return false;
3567 }
3568
Jamie Madill007530e2017-12-28 14:27:04 -05003569 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003571 context->handleError(InvalidOperation()
3572 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003573 return false;
3574 }
3575
Geoff Langca271392017-04-05 12:30:00 -04003576 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003577 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003578 if (!textureCaps.texturable)
3579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003580 context->handleError(InvalidOperation()
3581 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003582 return false;
3583 }
3584
Geoff Langdcab33b2015-07-21 13:03:16 -04003585 return true;
3586}
3587
3588bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003589 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003590 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003591{
Geoff Langa8406172015-07-21 16:53:39 -04003592 if (!context->getExtensions().eglImage)
3593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003594 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003595 return false;
3596 }
3597
3598 switch (target)
3599 {
3600 case GL_RENDERBUFFER:
3601 break;
3602
3603 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003604 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003605 return false;
3606 }
3607
Rafael Cintron05a449a2018-06-20 18:08:04 -07003608 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003609
Jamie Madill61e16b42017-06-19 11:13:23 -04003610 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003611 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003613 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003614 return false;
3615 }
3616
Geoff Langca271392017-04-05 12:30:00 -04003617 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003618 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003619 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003621 context->handleError(InvalidOperation()
3622 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003623 return false;
3624 }
3625
Geoff Langdcab33b2015-07-21 13:03:16 -04003626 return true;
3627}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003628
3629bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3630{
Geoff Lang36167ab2015-12-07 10:27:14 -05003631 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003632 {
3633 // The default VAO should always exist
3634 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003635 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003636 return false;
3637 }
3638
3639 return true;
3640}
3641
Geoff Langc5629752015-12-07 16:29:04 -05003642bool ValidateProgramBinaryBase(Context *context,
3643 GLuint program,
3644 GLenum binaryFormat,
3645 const void *binary,
3646 GLint length)
3647{
3648 Program *programObject = GetValidProgram(context, program);
3649 if (programObject == nullptr)
3650 {
3651 return false;
3652 }
3653
3654 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3655 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3656 programBinaryFormats.end())
3657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003658 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003659 return false;
3660 }
3661
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003662 if (context->hasActiveTransformFeedback(program))
3663 {
3664 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003665 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3666 "is associated with an active transform "
3667 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003668 return false;
3669 }
3670
Geoff Langc5629752015-12-07 16:29:04 -05003671 return true;
3672}
3673
3674bool ValidateGetProgramBinaryBase(Context *context,
3675 GLuint program,
3676 GLsizei bufSize,
3677 GLsizei *length,
3678 GLenum *binaryFormat,
3679 void *binary)
3680{
3681 Program *programObject = GetValidProgram(context, program);
3682 if (programObject == nullptr)
3683 {
3684 return false;
3685 }
3686
3687 if (!programObject->isLinked())
3688 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003689 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003690 return false;
3691 }
3692
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003693 if (context->getCaps().programBinaryFormats.empty())
3694 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003695 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003696 return false;
3697 }
3698
Geoff Langc5629752015-12-07 16:29:04 -05003699 return true;
3700}
Jamie Madillc29968b2016-01-20 11:17:23 -05003701
Jamie Madill5b772312018-03-08 20:28:32 -05003702bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003703{
3704 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003705 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003706 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003707 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3708 return false;
3709 }
3710 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3711 {
3712 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003713 return false;
3714 }
3715
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003716 ASSERT(context->getGLState().getDrawFramebuffer());
3717 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003718 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3719
3720 // This should come first before the check for the default frame buffer
3721 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3722 // rather than INVALID_OPERATION
3723 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3724 {
3725 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3726
3727 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003728 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3729 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003730 {
3731 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003732 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3733 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3734 // 3.1 is still a bit ambiguous about the error, but future specs are
3735 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003736 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003737 return false;
3738 }
3739 else if (bufs[colorAttachment] >= maxColorAttachment)
3740 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003741 context->handleError(InvalidOperation()
3742 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003743 return false;
3744 }
3745 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3746 frameBufferId != 0)
3747 {
3748 // INVALID_OPERATION-GL is bound to buffer and ith argument
3749 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003750 context->handleError(InvalidOperation()
3751 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003752 return false;
3753 }
3754 }
3755
3756 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3757 // and n is not 1 or bufs is bound to value other than BACK and NONE
3758 if (frameBufferId == 0)
3759 {
3760 if (n != 1)
3761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003762 context->handleError(InvalidOperation()
3763 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003764 return false;
3765 }
3766
3767 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3768 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003769 context->handleError(
3770 InvalidOperation()
3771 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003772 return false;
3773 }
3774 }
3775
3776 return true;
3777}
3778
Geoff Lang496c02d2016-10-20 11:38:11 -07003779bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003780 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003781 GLenum pname,
3782 GLsizei *length,
3783 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003784{
Geoff Lang496c02d2016-10-20 11:38:11 -07003785 if (length)
3786 {
3787 *length = 0;
3788 }
3789
3790 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3791 {
3792 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003793 InvalidOperation()
3794 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003795 return false;
3796 }
3797
Corentin Walleze4477002017-12-01 14:39:58 -05003798 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003799 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003800 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003801 return false;
3802 }
3803
Geoff Lang496c02d2016-10-20 11:38:11 -07003804 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003805 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003806 case GL_BUFFER_MAP_POINTER:
3807 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003808
Geoff Lang496c02d2016-10-20 11:38:11 -07003809 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003810 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003811 return false;
3812 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003813
3814 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3815 // target bound to zero generate an INVALID_OPERATION error."
3816 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003817 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003819 context->handleError(InvalidOperation()
3820 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003821 return false;
3822 }
3823
Geoff Lang496c02d2016-10-20 11:38:11 -07003824 if (length)
3825 {
3826 *length = 1;
3827 }
3828
Olli Etuaho4f667482016-03-30 15:56:35 +03003829 return true;
3830}
3831
Corentin Wallez336129f2017-10-17 15:55:40 -04003832bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003833{
Corentin Walleze4477002017-12-01 14:39:58 -05003834 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003835 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003836 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003837 return false;
3838 }
3839
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003840 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003841
3842 if (buffer == nullptr || !buffer->isMapped())
3843 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003844 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003845 return false;
3846 }
3847
3848 return true;
3849}
3850
3851bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003852 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003853 GLintptr offset,
3854 GLsizeiptr length,
3855 GLbitfield access)
3856{
Corentin Walleze4477002017-12-01 14:39:58 -05003857 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003859 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003860 return false;
3861 }
3862
Brandon Jones6cad5662017-06-14 13:25:13 -07003863 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003864 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003865 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3866 return false;
3867 }
3868
3869 if (length < 0)
3870 {
3871 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003872 return false;
3873 }
3874
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003875 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003876
3877 if (!buffer)
3878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003879 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003880 return false;
3881 }
3882
3883 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003884 CheckedNumeric<size_t> checkedOffset(offset);
3885 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003886
Jamie Madille2e406c2016-06-02 13:04:10 -04003887 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003889 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003890 return false;
3891 }
3892
3893 // Check for invalid bits in the mask
3894 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3895 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3896 GL_MAP_UNSYNCHRONIZED_BIT;
3897
3898 if (access & ~(allAccessBits))
3899 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003900 context->handleError(InvalidValue()
3901 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003902 return false;
3903 }
3904
3905 if (length == 0)
3906 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003907 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 return false;
3909 }
3910
3911 if (buffer->isMapped())
3912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003913 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 return false;
3915 }
3916
3917 // Check for invalid bit combinations
3918 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003920 context->handleError(InvalidOperation()
3921 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003922 return false;
3923 }
3924
3925 GLbitfield writeOnlyBits =
3926 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3927
3928 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003930 context->handleError(InvalidOperation()
3931 << "Invalid access bits when mapping buffer for reading: 0x"
3932 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003933 return false;
3934 }
3935
3936 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003938 context->handleError(
3939 InvalidOperation()
3940 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003941 return false;
3942 }
Geoff Lang79f71042017-08-14 16:43:43 -04003943
3944 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003945}
3946
3947bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003948 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003949 GLintptr offset,
3950 GLsizeiptr length)
3951{
Brandon Jones6cad5662017-06-14 13:25:13 -07003952 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003953 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003954 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3955 return false;
3956 }
3957
3958 if (length < 0)
3959 {
3960 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003961 return false;
3962 }
3963
Corentin Walleze4477002017-12-01 14:39:58 -05003964 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003967 return false;
3968 }
3969
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003970 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003971
3972 if (buffer == nullptr)
3973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003974 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003975 return false;
3976 }
3977
3978 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003980 context->handleError(InvalidOperation()
3981 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003982 return false;
3983 }
3984
3985 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003986 CheckedNumeric<size_t> checkedOffset(offset);
3987 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003988
Jamie Madille2e406c2016-06-02 13:04:10 -04003989 if (!checkedSize.IsValid() ||
3990 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003992 context->handleError(InvalidValue()
3993 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003994 return false;
3995 }
3996
3997 return true;
3998}
3999
Olli Etuaho41997e72016-03-10 13:38:39 +02004000bool ValidateGenOrDelete(Context *context, GLint n)
4001{
4002 if (n < 0)
4003 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004004 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004005 return false;
4006 }
4007 return true;
4008}
4009
Jamie Madill5b772312018-03-08 20:28:32 -05004010bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004011{
4012 if (!context->getExtensions().robustClientMemory)
4013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004014 context->handleError(InvalidOperation()
4015 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004016 return false;
4017 }
4018
4019 if (bufSize < 0)
4020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004021 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004022 return false;
4023 }
4024
4025 return true;
4026}
4027
Jamie Madill5b772312018-03-08 20:28:32 -05004028bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004029{
4030 if (bufSize < numParams)
4031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004032 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4033 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004034 return false;
4035 }
4036
4037 return true;
4038}
4039
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004040bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004041 GLenum target,
4042 GLenum attachment,
4043 GLenum pname,
4044 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004045{
Geoff Lange8afa902017-09-27 15:00:43 -04004046 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004048 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004049 return false;
4050 }
4051
4052 int clientVersion = context->getClientMajorVersion();
4053
4054 switch (pname)
4055 {
4056 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4057 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4058 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4059 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4060 break;
4061
Martin Radeve5285d22017-07-14 16:23:53 +03004062 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4063 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4064 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4065 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4066 if (clientVersion < 3 || !context->getExtensions().multiview)
4067 {
4068 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4069 return false;
4070 }
4071 break;
4072
Geoff Langff5b2d52016-09-07 11:32:23 -04004073 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4074 if (clientVersion < 3 && !context->getExtensions().sRGB)
4075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004076 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 return false;
4078 }
4079 break;
4080
4081 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4082 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4083 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4084 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4085 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4086 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4087 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4088 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4089 if (clientVersion < 3)
4090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004091 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004092 return false;
4093 }
4094 break;
4095
Jiawei Shaoa8802472018-05-28 11:17:47 +08004096 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4097 if (!context->getExtensions().geometryShader)
4098 {
4099 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4100 return false;
4101 }
4102 break;
4103
Geoff Langff5b2d52016-09-07 11:32:23 -04004104 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004105 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004106 return false;
4107 }
4108
4109 // Determine if the attachment is a valid enum
4110 switch (attachment)
4111 {
4112 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004113 case GL_DEPTH:
4114 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004115 if (clientVersion < 3)
4116 {
Geoff Langfa125c92017-10-24 13:01:46 -04004117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004118 return false;
4119 }
4120 break;
4121
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004122 case GL_DEPTH_STENCIL_ATTACHMENT:
4123 if (clientVersion < 3 && !context->isWebGL1())
4124 {
4125 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4126 return false;
4127 }
4128 break;
4129
Geoff Langfa125c92017-10-24 13:01:46 -04004130 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004131 case GL_DEPTH_ATTACHMENT:
4132 case GL_STENCIL_ATTACHMENT:
4133 break;
4134
4135 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004136 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4137 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004138 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4139 {
Geoff Langfa125c92017-10-24 13:01:46 -04004140 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004141 return false;
4142 }
4143 break;
4144 }
4145
4146 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4147 ASSERT(framebuffer);
4148
4149 if (framebuffer->id() == 0)
4150 {
4151 if (clientVersion < 3)
4152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004154 return false;
4155 }
4156
4157 switch (attachment)
4158 {
4159 case GL_BACK:
4160 case GL_DEPTH:
4161 case GL_STENCIL:
4162 break;
4163
4164 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 return false;
4167 }
4168 }
4169 else
4170 {
4171 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4172 {
4173 // Valid attachment query
4174 }
4175 else
4176 {
4177 switch (attachment)
4178 {
4179 case GL_DEPTH_ATTACHMENT:
4180 case GL_STENCIL_ATTACHMENT:
4181 break;
4182
4183 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004184 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004186 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004187 return false;
4188 }
4189 break;
4190
4191 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004192 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004193 return false;
4194 }
4195 }
4196 }
4197
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004198 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004199 if (attachmentObject)
4200 {
4201 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4202 attachmentObject->type() == GL_TEXTURE ||
4203 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4204
4205 switch (pname)
4206 {
4207 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4208 if (attachmentObject->type() != GL_RENDERBUFFER &&
4209 attachmentObject->type() != GL_TEXTURE)
4210 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004211 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004212 return false;
4213 }
4214 break;
4215
4216 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4217 if (attachmentObject->type() != GL_TEXTURE)
4218 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004219 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004220 return false;
4221 }
4222 break;
4223
4224 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4225 if (attachmentObject->type() != GL_TEXTURE)
4226 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004227 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004228 return false;
4229 }
4230 break;
4231
4232 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4233 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4234 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004236 return false;
4237 }
4238 break;
4239
4240 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4241 if (attachmentObject->type() != GL_TEXTURE)
4242 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004243 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004244 return false;
4245 }
4246 break;
4247
4248 default:
4249 break;
4250 }
4251 }
4252 else
4253 {
4254 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4255 // is NONE, then querying any other pname will generate INVALID_ENUM.
4256
4257 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4258 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4259 // INVALID_OPERATION for all other pnames
4260
4261 switch (pname)
4262 {
4263 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4264 break;
4265
4266 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4267 if (clientVersion < 3)
4268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004269 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004270 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004271 return false;
4272 }
4273 break;
4274
4275 default:
4276 if (clientVersion < 3)
4277 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004278 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004279 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004280 return false;
4281 }
4282 else
4283 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004284 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004285 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004286 return false;
4287 }
4288 }
4289 }
4290
Martin Radeve5285d22017-07-14 16:23:53 +03004291 if (numParams)
4292 {
4293 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4294 {
4295 // Only when the viewport offsets are queried we can have a varying number of output
4296 // parameters.
4297 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4298 *numParams = numViews * 2;
4299 }
4300 else
4301 {
4302 // For all other queries we can have only one output parameter.
4303 *numParams = 1;
4304 }
4305 }
4306
Geoff Langff5b2d52016-09-07 11:32:23 -04004307 return true;
4308}
4309
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004310bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004311 GLenum target,
4312 GLenum attachment,
4313 GLenum pname,
4314 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004315 GLsizei *length,
4316 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004317{
4318 if (!ValidateRobustEntryPoint(context, bufSize))
4319 {
4320 return false;
4321 }
4322
Brandon Jonesd1049182018-03-28 10:02:20 -07004323 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004324 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004325 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004326 {
4327 return false;
4328 }
4329
Brandon Jonesd1049182018-03-28 10:02:20 -07004330 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004331 {
4332 return false;
4333 }
4334
Brandon Jonesd1049182018-03-28 10:02:20 -07004335 SetRobustLengthParam(length, numParams);
4336
Geoff Langff5b2d52016-09-07 11:32:23 -04004337 return true;
4338}
4339
Jamie Madill5b772312018-03-08 20:28:32 -05004340bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004341 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004342 GLenum pname,
4343 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004344 GLsizei *length,
4345 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004346{
4347 if (!ValidateRobustEntryPoint(context, bufSize))
4348 {
4349 return false;
4350 }
4351
Brandon Jonesd1049182018-03-28 10:02:20 -07004352 GLsizei numParams = 0;
4353
4354 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004355 {
4356 return false;
4357 }
4358
Brandon Jonesd1049182018-03-28 10:02:20 -07004359 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004360 {
4361 return false;
4362 }
4363
Brandon Jonesd1049182018-03-28 10:02:20 -07004364 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004365 return true;
4366}
4367
Jamie Madill5b772312018-03-08 20:28:32 -05004368bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004369 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004370 GLenum pname,
4371 GLsizei bufSize,
4372 GLsizei *length,
4373 GLint64 *params)
4374{
Brandon Jonesd1049182018-03-28 10:02:20 -07004375 GLsizei numParams = 0;
4376
Geoff Langebebe1c2016-10-14 12:01:31 -04004377 if (!ValidateRobustEntryPoint(context, bufSize))
4378 {
4379 return false;
4380 }
4381
Brandon Jonesd1049182018-03-28 10:02:20 -07004382 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004383 {
4384 return false;
4385 }
4386
Brandon Jonesd1049182018-03-28 10:02:20 -07004387 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004388 {
4389 return false;
4390 }
4391
Brandon Jonesd1049182018-03-28 10:02:20 -07004392 SetRobustLengthParam(length, numParams);
4393
Geoff Langff5b2d52016-09-07 11:32:23 -04004394 return true;
4395}
4396
Jamie Madill5b772312018-03-08 20:28:32 -05004397bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004398{
4399 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004400 if (numParams)
4401 {
4402 *numParams = 1;
4403 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004404
4405 Program *programObject = GetValidProgram(context, program);
4406 if (!programObject)
4407 {
4408 return false;
4409 }
4410
4411 switch (pname)
4412 {
4413 case GL_DELETE_STATUS:
4414 case GL_LINK_STATUS:
4415 case GL_VALIDATE_STATUS:
4416 case GL_INFO_LOG_LENGTH:
4417 case GL_ATTACHED_SHADERS:
4418 case GL_ACTIVE_ATTRIBUTES:
4419 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4420 case GL_ACTIVE_UNIFORMS:
4421 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4422 break;
4423
4424 case GL_PROGRAM_BINARY_LENGTH:
4425 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004427 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4428 "requires GL_OES_get_program_binary or "
4429 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004430 return false;
4431 }
4432 break;
4433
4434 case GL_ACTIVE_UNIFORM_BLOCKS:
4435 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4436 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4437 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4438 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4439 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4440 if (context->getClientMajorVersion() < 3)
4441 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004442 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004443 return false;
4444 }
4445 break;
4446
Yunchao He61afff12017-03-14 15:34:03 +08004447 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004448 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004449 if (context->getClientVersion() < Version(3, 1))
4450 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004451 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004452 return false;
4453 }
4454 break;
4455
Jiawei Shao6ae51612018-02-23 14:03:25 +08004456 case GL_COMPUTE_WORK_GROUP_SIZE:
4457 if (context->getClientVersion() < Version(3, 1))
4458 {
4459 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4460 return false;
4461 }
4462
4463 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4464 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4465 // program which has not been linked successfully, or which does not contain objects to
4466 // form a compute shader.
4467 if (!programObject->isLinked())
4468 {
4469 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4470 return false;
4471 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004472 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004473 {
4474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4475 return false;
4476 }
4477 break;
4478
Jiawei Shao447bfac2018-03-14 14:23:40 +08004479 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4480 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4481 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4482 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4483 if (!context->getExtensions().geometryShader)
4484 {
4485 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4486 return false;
4487 }
4488
4489 // [EXT_geometry_shader] Chapter 7.12
4490 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4491 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4492 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4493 // successfully, or which does not contain objects to form a geometry shader.
4494 if (!programObject->isLinked())
4495 {
4496 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4497 return false;
4498 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004499 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004500 {
4501 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4502 return false;
4503 }
4504 break;
4505
Geoff Langff5b2d52016-09-07 11:32:23 -04004506 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004507 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004508 return false;
4509 }
4510
4511 return true;
4512}
4513
4514bool ValidateGetProgramivRobustANGLE(Context *context,
4515 GLuint program,
4516 GLenum pname,
4517 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004518 GLsizei *length,
4519 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004520{
4521 if (!ValidateRobustEntryPoint(context, bufSize))
4522 {
4523 return false;
4524 }
4525
Brandon Jonesd1049182018-03-28 10:02:20 -07004526 GLsizei numParams = 0;
4527
4528 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004529 {
4530 return false;
4531 }
4532
Brandon Jonesd1049182018-03-28 10:02:20 -07004533 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004534 {
4535 return false;
4536 }
4537
Brandon Jonesd1049182018-03-28 10:02:20 -07004538 SetRobustLengthParam(length, numParams);
4539
Geoff Langff5b2d52016-09-07 11:32:23 -04004540 return true;
4541}
4542
Geoff Lang740d9022016-10-07 11:20:52 -04004543bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4544 GLenum target,
4545 GLenum pname,
4546 GLsizei bufSize,
4547 GLsizei *length,
4548 GLint *params)
4549{
4550 if (!ValidateRobustEntryPoint(context, bufSize))
4551 {
4552 return false;
4553 }
4554
Brandon Jonesd1049182018-03-28 10:02:20 -07004555 GLsizei numParams = 0;
4556
4557 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004558 {
4559 return false;
4560 }
4561
Brandon Jonesd1049182018-03-28 10:02:20 -07004562 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004563 {
4564 return false;
4565 }
4566
Brandon Jonesd1049182018-03-28 10:02:20 -07004567 SetRobustLengthParam(length, numParams);
4568
Geoff Lang740d9022016-10-07 11:20:52 -04004569 return true;
4570}
4571
Geoff Langd7d0ed32016-10-07 11:33:51 -04004572bool ValidateGetShaderivRobustANGLE(Context *context,
4573 GLuint shader,
4574 GLenum pname,
4575 GLsizei bufSize,
4576 GLsizei *length,
4577 GLint *params)
4578{
4579 if (!ValidateRobustEntryPoint(context, bufSize))
4580 {
4581 return false;
4582 }
4583
Brandon Jonesd1049182018-03-28 10:02:20 -07004584 GLsizei numParams = 0;
4585
4586 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004587 {
4588 return false;
4589 }
4590
Brandon Jonesd1049182018-03-28 10:02:20 -07004591 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004592 {
4593 return false;
4594 }
4595
Brandon Jonesd1049182018-03-28 10:02:20 -07004596 SetRobustLengthParam(length, numParams);
4597
Geoff Langd7d0ed32016-10-07 11:33:51 -04004598 return true;
4599}
4600
Geoff Langc1984ed2016-10-07 12:41:00 -04004601bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004602 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004603 GLenum pname,
4604 GLsizei bufSize,
4605 GLsizei *length,
4606 GLfloat *params)
4607{
4608 if (!ValidateRobustEntryPoint(context, bufSize))
4609 {
4610 return false;
4611 }
4612
Brandon Jonesd1049182018-03-28 10:02:20 -07004613 GLsizei numParams = 0;
4614
4615 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004616 {
4617 return false;
4618 }
4619
Brandon Jonesd1049182018-03-28 10:02:20 -07004620 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004621 {
4622 return false;
4623 }
4624
Brandon Jonesd1049182018-03-28 10:02:20 -07004625 SetRobustLengthParam(length, numParams);
4626
Geoff Langc1984ed2016-10-07 12:41:00 -04004627 return true;
4628}
4629
Geoff Langc1984ed2016-10-07 12:41:00 -04004630bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004631 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004632 GLenum pname,
4633 GLsizei bufSize,
4634 GLsizei *length,
4635 GLint *params)
4636{
Brandon Jonesd1049182018-03-28 10:02:20 -07004637
Geoff Langc1984ed2016-10-07 12:41:00 -04004638 if (!ValidateRobustEntryPoint(context, bufSize))
4639 {
4640 return false;
4641 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004642 GLsizei numParams = 0;
4643 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004644 {
4645 return false;
4646 }
4647
Brandon Jonesd1049182018-03-28 10:02:20 -07004648 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004649 {
4650 return false;
4651 }
4652
Brandon Jonesd1049182018-03-28 10:02:20 -07004653 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004654 return true;
4655}
4656
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004657bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4658 TextureType target,
4659 GLenum pname,
4660 GLsizei bufSize,
4661 GLsizei *length,
4662 GLint *params)
4663{
4664 UNIMPLEMENTED();
4665 return false;
4666}
4667
4668bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4669 TextureType target,
4670 GLenum pname,
4671 GLsizei bufSize,
4672 GLsizei *length,
4673 GLuint *params)
4674{
4675 UNIMPLEMENTED();
4676 return false;
4677}
4678
Geoff Langc1984ed2016-10-07 12:41:00 -04004679bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004680 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004681 GLenum pname,
4682 GLsizei bufSize,
4683 const GLfloat *params)
4684{
4685 if (!ValidateRobustEntryPoint(context, bufSize))
4686 {
4687 return false;
4688 }
4689
4690 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4691}
4692
Geoff Langc1984ed2016-10-07 12:41:00 -04004693bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004694 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004695 GLenum pname,
4696 GLsizei bufSize,
4697 const GLint *params)
4698{
4699 if (!ValidateRobustEntryPoint(context, bufSize))
4700 {
4701 return false;
4702 }
4703
4704 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4705}
4706
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004707bool ValidateTexParameterIivRobustANGLE(Context *context,
4708 TextureType target,
4709 GLenum pname,
4710 GLsizei bufSize,
4711 const GLint *params)
4712{
4713 UNIMPLEMENTED();
4714 return false;
4715}
4716
4717bool ValidateTexParameterIuivRobustANGLE(Context *context,
4718 TextureType target,
4719 GLenum pname,
4720 GLsizei bufSize,
4721 const GLuint *params)
4722{
4723 UNIMPLEMENTED();
4724 return false;
4725}
4726
Geoff Langc1984ed2016-10-07 12:41:00 -04004727bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4728 GLuint sampler,
4729 GLenum pname,
4730 GLuint bufSize,
4731 GLsizei *length,
4732 GLfloat *params)
4733{
4734 if (!ValidateRobustEntryPoint(context, bufSize))
4735 {
4736 return false;
4737 }
4738
Brandon Jonesd1049182018-03-28 10:02:20 -07004739 GLsizei numParams = 0;
4740
4741 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004742 {
4743 return false;
4744 }
4745
Brandon Jonesd1049182018-03-28 10:02:20 -07004746 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004747 {
4748 return false;
4749 }
4750
Brandon Jonesd1049182018-03-28 10:02:20 -07004751 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004752 return true;
4753}
4754
Geoff Langc1984ed2016-10-07 12:41:00 -04004755bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4756 GLuint sampler,
4757 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004758 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004759 GLsizei *length,
4760 GLint *params)
4761{
4762 if (!ValidateRobustEntryPoint(context, bufSize))
4763 {
4764 return false;
4765 }
4766
Brandon Jonesd1049182018-03-28 10:02:20 -07004767 GLsizei numParams = 0;
4768
4769 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004770 {
4771 return false;
4772 }
4773
Brandon Jonesd1049182018-03-28 10:02:20 -07004774 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004775 {
4776 return false;
4777 }
4778
Brandon Jonesd1049182018-03-28 10:02:20 -07004779 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004780 return true;
4781}
4782
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004783bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4784 GLuint sampler,
4785 GLenum pname,
4786 GLsizei bufSize,
4787 GLsizei *length,
4788 GLint *params)
4789{
4790 UNIMPLEMENTED();
4791 return false;
4792}
4793
4794bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4795 GLuint sampler,
4796 GLenum pname,
4797 GLsizei bufSize,
4798 GLsizei *length,
4799 GLuint *params)
4800{
4801 UNIMPLEMENTED();
4802 return false;
4803}
4804
Geoff Langc1984ed2016-10-07 12:41:00 -04004805bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4806 GLuint sampler,
4807 GLenum pname,
4808 GLsizei bufSize,
4809 const GLfloat *params)
4810{
4811 if (!ValidateRobustEntryPoint(context, bufSize))
4812 {
4813 return false;
4814 }
4815
4816 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4817}
4818
Geoff Langc1984ed2016-10-07 12:41:00 -04004819bool ValidateSamplerParameterivRobustANGLE(Context *context,
4820 GLuint sampler,
4821 GLenum pname,
4822 GLsizei bufSize,
4823 const GLint *params)
4824{
4825 if (!ValidateRobustEntryPoint(context, bufSize))
4826 {
4827 return false;
4828 }
4829
4830 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4831}
4832
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004833bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4834 GLuint sampler,
4835 GLenum pname,
4836 GLsizei bufSize,
4837 const GLint *param)
4838{
4839 UNIMPLEMENTED();
4840 return false;
4841}
4842
4843bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4844 GLuint sampler,
4845 GLenum pname,
4846 GLsizei bufSize,
4847 const GLuint *param)
4848{
4849 UNIMPLEMENTED();
4850 return false;
4851}
4852
Geoff Lang0b031062016-10-13 14:30:04 -04004853bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4854 GLuint index,
4855 GLenum pname,
4856 GLsizei bufSize,
4857 GLsizei *length,
4858 GLfloat *params)
4859{
4860 if (!ValidateRobustEntryPoint(context, bufSize))
4861 {
4862 return false;
4863 }
4864
Brandon Jonesd1049182018-03-28 10:02:20 -07004865 GLsizei writeLength = 0;
4866
4867 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004868 {
4869 return false;
4870 }
4871
Brandon Jonesd1049182018-03-28 10:02:20 -07004872 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004873 {
4874 return false;
4875 }
4876
Brandon Jonesd1049182018-03-28 10:02:20 -07004877 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004878 return true;
4879}
4880
Geoff Lang0b031062016-10-13 14:30:04 -04004881bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4882 GLuint index,
4883 GLenum pname,
4884 GLsizei bufSize,
4885 GLsizei *length,
4886 GLint *params)
4887{
4888 if (!ValidateRobustEntryPoint(context, bufSize))
4889 {
4890 return false;
4891 }
4892
Brandon Jonesd1049182018-03-28 10:02:20 -07004893 GLsizei writeLength = 0;
4894
4895 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004896 {
4897 return false;
4898 }
4899
Brandon Jonesd1049182018-03-28 10:02:20 -07004900 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004901 {
4902 return false;
4903 }
4904
Brandon Jonesd1049182018-03-28 10:02:20 -07004905 SetRobustLengthParam(length, writeLength);
4906
Geoff Lang0b031062016-10-13 14:30:04 -04004907 return true;
4908}
4909
Geoff Lang0b031062016-10-13 14:30:04 -04004910bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4911 GLuint index,
4912 GLenum pname,
4913 GLsizei bufSize,
4914 GLsizei *length,
4915 void **pointer)
4916{
4917 if (!ValidateRobustEntryPoint(context, bufSize))
4918 {
4919 return false;
4920 }
4921
Brandon Jonesd1049182018-03-28 10:02:20 -07004922 GLsizei writeLength = 0;
4923
4924 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004925 {
4926 return false;
4927 }
4928
Brandon Jonesd1049182018-03-28 10:02:20 -07004929 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004930 {
4931 return false;
4932 }
4933
Brandon Jonesd1049182018-03-28 10:02:20 -07004934 SetRobustLengthParam(length, writeLength);
4935
Geoff Lang0b031062016-10-13 14:30:04 -04004936 return true;
4937}
4938
Geoff Lang0b031062016-10-13 14:30:04 -04004939bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4940 GLuint index,
4941 GLenum pname,
4942 GLsizei bufSize,
4943 GLsizei *length,
4944 GLint *params)
4945{
4946 if (!ValidateRobustEntryPoint(context, bufSize))
4947 {
4948 return false;
4949 }
4950
Brandon Jonesd1049182018-03-28 10:02:20 -07004951 GLsizei writeLength = 0;
4952
4953 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004954 {
4955 return false;
4956 }
4957
Brandon Jonesd1049182018-03-28 10:02:20 -07004958 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004959 {
4960 return false;
4961 }
4962
Brandon Jonesd1049182018-03-28 10:02:20 -07004963 SetRobustLengthParam(length, writeLength);
4964
Geoff Lang0b031062016-10-13 14:30:04 -04004965 return true;
4966}
4967
Geoff Lang0b031062016-10-13 14:30:04 -04004968bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4969 GLuint index,
4970 GLenum pname,
4971 GLsizei bufSize,
4972 GLsizei *length,
4973 GLuint *params)
4974{
4975 if (!ValidateRobustEntryPoint(context, bufSize))
4976 {
4977 return false;
4978 }
4979
Brandon Jonesd1049182018-03-28 10:02:20 -07004980 GLsizei writeLength = 0;
4981
4982 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004983 {
4984 return false;
4985 }
4986
Brandon Jonesd1049182018-03-28 10:02:20 -07004987 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004988 {
4989 return false;
4990 }
4991
Brandon Jonesd1049182018-03-28 10:02:20 -07004992 SetRobustLengthParam(length, writeLength);
4993
Geoff Lang0b031062016-10-13 14:30:04 -04004994 return true;
4995}
4996
Geoff Lang6899b872016-10-14 11:30:13 -04004997bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4998 GLuint program,
4999 GLuint uniformBlockIndex,
5000 GLenum pname,
5001 GLsizei bufSize,
5002 GLsizei *length,
5003 GLint *params)
5004{
5005 if (!ValidateRobustEntryPoint(context, bufSize))
5006 {
5007 return false;
5008 }
5009
Brandon Jonesd1049182018-03-28 10:02:20 -07005010 GLsizei writeLength = 0;
5011
5012 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5013 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005014 {
5015 return false;
5016 }
5017
Brandon Jonesd1049182018-03-28 10:02:20 -07005018 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005019 {
5020 return false;
5021 }
5022
Brandon Jonesd1049182018-03-28 10:02:20 -07005023 SetRobustLengthParam(length, writeLength);
5024
Geoff Lang6899b872016-10-14 11:30:13 -04005025 return true;
5026}
5027
Brandon Jones416aaf92018-04-10 08:10:16 -07005028bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005029 GLenum target,
5030 GLenum internalformat,
5031 GLenum pname,
5032 GLsizei bufSize,
5033 GLsizei *length,
5034 GLint *params)
5035{
5036 if (!ValidateRobustEntryPoint(context, bufSize))
5037 {
5038 return false;
5039 }
5040
Brandon Jonesd1049182018-03-28 10:02:20 -07005041 GLsizei numParams = 0;
5042
5043 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5044 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005045 {
5046 return false;
5047 }
5048
Brandon Jonesd1049182018-03-28 10:02:20 -07005049 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005050 {
5051 return false;
5052 }
5053
Brandon Jonesd1049182018-03-28 10:02:20 -07005054 SetRobustLengthParam(length, numParams);
5055
Geoff Lang0a9661f2016-10-20 10:59:20 -07005056 return true;
5057}
5058
Jamie Madill5b772312018-03-08 20:28:32 -05005059bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005060 GLuint attribIndex,
5061 GLint size,
5062 GLenum type,
5063 GLboolean pureInteger)
5064{
5065 const Caps &caps = context->getCaps();
5066 if (attribIndex >= caps.maxVertexAttributes)
5067 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005068 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005069 return false;
5070 }
5071
5072 if (size < 1 || size > 4)
5073 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005074 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005075 return false;
Shao80957d92017-02-20 21:25:59 +08005076 }
5077
5078 switch (type)
5079 {
5080 case GL_BYTE:
5081 case GL_UNSIGNED_BYTE:
5082 case GL_SHORT:
5083 case GL_UNSIGNED_SHORT:
5084 break;
5085
5086 case GL_INT:
5087 case GL_UNSIGNED_INT:
5088 if (context->getClientMajorVersion() < 3)
5089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005090 context->handleError(InvalidEnum()
5091 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005092 return false;
5093 }
5094 break;
5095
5096 case GL_FIXED:
5097 case GL_FLOAT:
5098 if (pureInteger)
5099 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005100 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005101 return false;
5102 }
5103 break;
5104
5105 case GL_HALF_FLOAT:
5106 if (context->getClientMajorVersion() < 3)
5107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005108 context->handleError(InvalidEnum()
5109 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005110 return false;
5111 }
5112 if (pureInteger)
5113 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005114 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005115 return false;
5116 }
5117 break;
5118
5119 case GL_INT_2_10_10_10_REV:
5120 case GL_UNSIGNED_INT_2_10_10_10_REV:
5121 if (context->getClientMajorVersion() < 3)
5122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005123 context->handleError(InvalidEnum()
5124 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005125 return false;
5126 }
5127 if (pureInteger)
5128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005130 return false;
5131 }
5132 if (size != 4)
5133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005134 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5135 "UNSIGNED_INT_2_10_10_10_REV and "
5136 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005137 return false;
5138 }
5139 break;
5140
5141 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005142 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005143 return false;
5144 }
5145
5146 return true;
5147}
5148
Geoff Lang76e65652017-03-27 14:58:02 -04005149// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5150// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5151// specified clear value and the type of a buffer that is being cleared generates an
5152// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005153bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005154 GLint drawbuffer,
5155 const GLenum *validComponentTypes,
5156 size_t validComponentTypeCount)
5157{
5158 const FramebufferAttachment *attachment =
5159 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5160 if (attachment)
5161 {
5162 GLenum componentType = attachment->getFormat().info->componentType;
5163 const GLenum *end = validComponentTypes + validComponentTypeCount;
5164 if (std::find(validComponentTypes, end, componentType) == end)
5165 {
5166 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005167 InvalidOperation()
5168 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005169 return false;
5170 }
5171 }
5172
5173 return true;
5174}
5175
Jamie Madill5b772312018-03-08 20:28:32 -05005176bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005177{
5178 if (!ValidateRobustEntryPoint(context, dataSize))
5179 {
5180 return false;
5181 }
5182
Corentin Wallez336129f2017-10-17 15:55:40 -04005183 gl::Buffer *pixelUnpackBuffer =
5184 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005185 if (pixelUnpackBuffer == nullptr)
5186 {
5187 if (dataSize < imageSize)
5188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005189 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005190 }
5191 }
5192 return true;
5193}
5194
Jamie Madill5b772312018-03-08 20:28:32 -05005195bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005196 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005197 GLenum pname,
5198 bool pointerVersion,
5199 GLsizei *numParams)
5200{
5201 if (numParams)
5202 {
5203 *numParams = 0;
5204 }
5205
Corentin Walleze4477002017-12-01 14:39:58 -05005206 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005207 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005208 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005209 return false;
5210 }
5211
5212 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5213 if (!buffer)
5214 {
5215 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005216 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005217 return false;
5218 }
5219
5220 const Extensions &extensions = context->getExtensions();
5221
5222 switch (pname)
5223 {
5224 case GL_BUFFER_USAGE:
5225 case GL_BUFFER_SIZE:
5226 break;
5227
5228 case GL_BUFFER_ACCESS_OES:
5229 if (!extensions.mapBuffer)
5230 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005231 context->handleError(InvalidEnum()
5232 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005233 return false;
5234 }
5235 break;
5236
5237 case GL_BUFFER_MAPPED:
5238 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5239 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5240 !extensions.mapBufferRange)
5241 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005242 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5243 "GL_OES_mapbuffer or "
5244 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 return false;
5246 }
5247 break;
5248
5249 case GL_BUFFER_MAP_POINTER:
5250 if (!pointerVersion)
5251 {
5252 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005253 InvalidEnum()
5254 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005255 return false;
5256 }
5257 break;
5258
5259 case GL_BUFFER_ACCESS_FLAGS:
5260 case GL_BUFFER_MAP_OFFSET:
5261 case GL_BUFFER_MAP_LENGTH:
5262 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5263 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005264 context->handleError(InvalidEnum()
5265 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005266 return false;
5267 }
5268 break;
5269
5270 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005271 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005272 return false;
5273 }
5274
5275 // All buffer parameter queries return one value.
5276 if (numParams)
5277 {
5278 *numParams = 1;
5279 }
5280
5281 return true;
5282}
5283
5284bool ValidateGetRenderbufferParameterivBase(Context *context,
5285 GLenum target,
5286 GLenum pname,
5287 GLsizei *length)
5288{
5289 if (length)
5290 {
5291 *length = 0;
5292 }
5293
5294 if (target != GL_RENDERBUFFER)
5295 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005296 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005297 return false;
5298 }
5299
5300 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5301 if (renderbuffer == nullptr)
5302 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005303 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005304 return false;
5305 }
5306
5307 switch (pname)
5308 {
5309 case GL_RENDERBUFFER_WIDTH:
5310 case GL_RENDERBUFFER_HEIGHT:
5311 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5312 case GL_RENDERBUFFER_RED_SIZE:
5313 case GL_RENDERBUFFER_GREEN_SIZE:
5314 case GL_RENDERBUFFER_BLUE_SIZE:
5315 case GL_RENDERBUFFER_ALPHA_SIZE:
5316 case GL_RENDERBUFFER_DEPTH_SIZE:
5317 case GL_RENDERBUFFER_STENCIL_SIZE:
5318 break;
5319
5320 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5321 if (!context->getExtensions().framebufferMultisample)
5322 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005323 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005324 return false;
5325 }
5326 break;
5327
5328 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005329 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005330 return false;
5331 }
5332
5333 if (length)
5334 {
5335 *length = 1;
5336 }
5337 return true;
5338}
5339
5340bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5341{
5342 if (length)
5343 {
5344 *length = 0;
5345 }
5346
5347 if (GetValidShader(context, shader) == nullptr)
5348 {
5349 return false;
5350 }
5351
5352 switch (pname)
5353 {
5354 case GL_SHADER_TYPE:
5355 case GL_DELETE_STATUS:
5356 case GL_COMPILE_STATUS:
5357 case GL_INFO_LOG_LENGTH:
5358 case GL_SHADER_SOURCE_LENGTH:
5359 break;
5360
5361 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5362 if (!context->getExtensions().translatedShaderSource)
5363 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005365 return false;
5366 }
5367 break;
5368
5369 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005370 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005371 return false;
5372 }
5373
5374 if (length)
5375 {
5376 *length = 1;
5377 }
5378 return true;
5379}
5380
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005381bool ValidateGetTexParameterBase(Context *context,
5382 TextureType target,
5383 GLenum pname,
5384 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005385{
5386 if (length)
5387 {
5388 *length = 0;
5389 }
5390
5391 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5392 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005393 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005394 return false;
5395 }
5396
5397 if (context->getTargetTexture(target) == nullptr)
5398 {
5399 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005400 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005401 return false;
5402 }
5403
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005404 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5405 {
5406 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5407 return false;
5408 }
5409
Jamie Madillbe849e42017-05-02 15:49:00 -04005410 switch (pname)
5411 {
5412 case GL_TEXTURE_MAG_FILTER:
5413 case GL_TEXTURE_MIN_FILTER:
5414 case GL_TEXTURE_WRAP_S:
5415 case GL_TEXTURE_WRAP_T:
5416 break;
5417
5418 case GL_TEXTURE_USAGE_ANGLE:
5419 if (!context->getExtensions().textureUsage)
5420 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005422 return false;
5423 }
5424 break;
5425
5426 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005427 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005428 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005429 return false;
5430 }
5431 break;
5432
5433 case GL_TEXTURE_IMMUTABLE_FORMAT:
5434 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5435 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005436 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005437 return false;
5438 }
5439 break;
5440
5441 case GL_TEXTURE_WRAP_R:
5442 case GL_TEXTURE_IMMUTABLE_LEVELS:
5443 case GL_TEXTURE_SWIZZLE_R:
5444 case GL_TEXTURE_SWIZZLE_G:
5445 case GL_TEXTURE_SWIZZLE_B:
5446 case GL_TEXTURE_SWIZZLE_A:
5447 case GL_TEXTURE_BASE_LEVEL:
5448 case GL_TEXTURE_MAX_LEVEL:
5449 case GL_TEXTURE_MIN_LOD:
5450 case GL_TEXTURE_MAX_LOD:
5451 case GL_TEXTURE_COMPARE_MODE:
5452 case GL_TEXTURE_COMPARE_FUNC:
5453 if (context->getClientMajorVersion() < 3)
5454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005455 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005456 return false;
5457 }
5458 break;
5459
5460 case GL_TEXTURE_SRGB_DECODE_EXT:
5461 if (!context->getExtensions().textureSRGBDecode)
5462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005463 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005464 return false;
5465 }
5466 break;
5467
Yunchao Hebacaa712018-01-30 14:01:39 +08005468 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5469 if (context->getClientVersion() < Version(3, 1))
5470 {
5471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5472 return false;
5473 }
5474 break;
5475
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005476 case GL_GENERATE_MIPMAP:
5477 case GL_TEXTURE_CROP_RECT_OES:
5478 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5479 // after GL_OES_draw_texture functionality implemented
5480 if (context->getClientMajorVersion() > 1)
5481 {
5482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5483 return false;
5484 }
5485 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005486 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005487 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005488 return false;
5489 }
5490
5491 if (length)
5492 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005493 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005494 }
5495 return true;
5496}
5497
5498bool ValidateGetVertexAttribBase(Context *context,
5499 GLuint index,
5500 GLenum pname,
5501 GLsizei *length,
5502 bool pointer,
5503 bool pureIntegerEntryPoint)
5504{
5505 if (length)
5506 {
5507 *length = 0;
5508 }
5509
5510 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005512 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005513 return false;
5514 }
5515
5516 if (index >= context->getCaps().maxVertexAttributes)
5517 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005518 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005519 return false;
5520 }
5521
5522 if (pointer)
5523 {
5524 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5525 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005526 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005527 return false;
5528 }
5529 }
5530 else
5531 {
5532 switch (pname)
5533 {
5534 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5535 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5536 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5537 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5538 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5539 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5540 case GL_CURRENT_VERTEX_ATTRIB:
5541 break;
5542
5543 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5544 static_assert(
5545 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5546 "ANGLE extension enums not equal to GL enums.");
5547 if (context->getClientMajorVersion() < 3 &&
5548 !context->getExtensions().instancedArrays)
5549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005550 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5551 "requires OpenGL ES 3.0 or "
5552 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005553 return false;
5554 }
5555 break;
5556
5557 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5558 if (context->getClientMajorVersion() < 3)
5559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005560 context->handleError(
5561 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005562 return false;
5563 }
5564 break;
5565
5566 case GL_VERTEX_ATTRIB_BINDING:
5567 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5568 if (context->getClientVersion() < ES_3_1)
5569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005570 context->handleError(InvalidEnum()
5571 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005572 return false;
5573 }
5574 break;
5575
5576 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005577 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005578 return false;
5579 }
5580 }
5581
5582 if (length)
5583 {
5584 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5585 {
5586 *length = 4;
5587 }
5588 else
5589 {
5590 *length = 1;
5591 }
5592 }
5593
5594 return true;
5595}
5596
Jamie Madill4928b7c2017-06-20 12:57:39 -04005597bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005598 GLint x,
5599 GLint y,
5600 GLsizei width,
5601 GLsizei height,
5602 GLenum format,
5603 GLenum type,
5604 GLsizei bufSize,
5605 GLsizei *length,
5606 GLsizei *columns,
5607 GLsizei *rows,
5608 void *pixels)
5609{
5610 if (length != nullptr)
5611 {
5612 *length = 0;
5613 }
5614 if (rows != nullptr)
5615 {
5616 *rows = 0;
5617 }
5618 if (columns != nullptr)
5619 {
5620 *columns = 0;
5621 }
5622
5623 if (width < 0 || height < 0)
5624 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005625 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005626 return false;
5627 }
5628
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005629 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005630
Jamie Madill427064d2018-04-13 16:20:34 -04005631 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005632 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005633 return false;
5634 }
5635
Jamie Madille98b1b52018-03-08 09:47:23 -05005636 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005637 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005638 return false;
5639 }
5640
Jamie Madill690c8eb2018-03-12 15:20:03 -04005641 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005642 ASSERT(framebuffer);
5643
5644 if (framebuffer->getReadBufferState() == GL_NONE)
5645 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005647 return false;
5648 }
5649
5650 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5651 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5652 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5653 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5654 // situation is an application error that would lead to a crash in ANGLE.
5655 if (readBuffer == nullptr)
5656 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005657 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005658 return false;
5659 }
5660
Martin Radev28031682017-07-28 14:47:56 +03005661 // ANGLE_multiview, Revision 1:
5662 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005663 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5664 // in the current read framebuffer is more than one.
5665 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005666 {
5667 context->handleError(InvalidFramebufferOperation()
5668 << "Attempting to read from a multi-view framebuffer.");
5669 return false;
5670 }
5671
Geoff Lang280ba992017-04-18 16:30:58 -04005672 if (context->getExtensions().webglCompatibility)
5673 {
5674 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5675 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5676 // and type before validating the combination of format and type. However, the
5677 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5678 // verifies that GL_INVALID_OPERATION is generated.
5679 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5680 // dEQP/WebGL.
5681 if (!ValidReadPixelsFormatEnum(context, format))
5682 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005683 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005684 return false;
5685 }
5686
5687 if (!ValidReadPixelsTypeEnum(context, type))
5688 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005689 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005690 return false;
5691 }
5692 }
5693
Jamie Madill690c8eb2018-03-12 15:20:03 -04005694 GLenum currentFormat = GL_NONE;
5695 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5696
5697 GLenum currentType = GL_NONE;
5698 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5699
Jamie Madillbe849e42017-05-02 15:49:00 -04005700 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5701
5702 bool validFormatTypeCombination =
5703 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5704
5705 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5706 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005708 return false;
5709 }
5710
5711 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005712 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005713 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5714 {
5715 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005716 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005717 return false;
5718 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005719 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5720 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5721 {
5722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5723 return false;
5724 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005725
5726 // .. the data would be packed to the buffer object such that the memory writes required
5727 // would exceed the data store size.
5728 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5729 const gl::Extents size(width, height, 1);
5730 const auto &pack = context->getGLState().getPackState();
5731
Jamie Madillca2ff382018-07-11 09:01:17 -04005732 GLuint endByte = 0;
5733 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005734 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005735 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005736 return false;
5737 }
5738
Jamie Madillbe849e42017-05-02 15:49:00 -04005739 if (bufSize >= 0)
5740 {
5741 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5742 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005743 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005744 return false;
5745 }
5746 }
5747
5748 if (pixelPackBuffer != nullptr)
5749 {
5750 CheckedNumeric<size_t> checkedEndByte(endByte);
5751 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5752 checkedEndByte += checkedOffset;
5753
5754 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5755 {
5756 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005757 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005758 return false;
5759 }
5760 }
5761
5762 if (pixelPackBuffer == nullptr && length != nullptr)
5763 {
5764 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5765 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005766 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005767 return false;
5768 }
5769
5770 *length = static_cast<GLsizei>(endByte);
5771 }
5772
Geoff Langa953b522018-02-21 16:56:23 -05005773 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005774 angle::CheckedNumeric<int> clippedExtent(length);
5775 if (start < 0)
5776 {
5777 // "subtract" the area that is less than 0
5778 clippedExtent += start;
5779 }
5780
Geoff Langa953b522018-02-21 16:56:23 -05005781 angle::CheckedNumeric<int> readExtent = start;
5782 readExtent += length;
5783 if (!readExtent.IsValid())
5784 {
5785 return false;
5786 }
5787
5788 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005789 {
5790 // Subtract the region to the right of the read buffer
5791 clippedExtent -= (readExtent - bufferSize);
5792 }
5793
5794 if (!clippedExtent.IsValid())
5795 {
Geoff Langa953b522018-02-21 16:56:23 -05005796 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005797 }
5798
Geoff Langa953b522018-02-21 16:56:23 -05005799 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5800 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 };
5802
Geoff Langa953b522018-02-21 16:56:23 -05005803 GLsizei writtenColumns = 0;
5804 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5805 {
5806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5807 return false;
5808 }
5809
5810 GLsizei writtenRows = 0;
5811 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5812 {
5813 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5814 return false;
5815 }
5816
Jamie Madillbe849e42017-05-02 15:49:00 -04005817 if (columns != nullptr)
5818 {
Geoff Langa953b522018-02-21 16:56:23 -05005819 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005820 }
5821
5822 if (rows != nullptr)
5823 {
Geoff Langa953b522018-02-21 16:56:23 -05005824 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005825 }
5826
5827 return true;
5828}
5829
5830template <typename ParamType>
5831bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005832 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005833 GLenum pname,
5834 GLsizei bufSize,
5835 const ParamType *params)
5836{
5837 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005839 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005840 return false;
5841 }
5842
5843 if (context->getTargetTexture(target) == nullptr)
5844 {
5845 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005846 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005847 return false;
5848 }
5849
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005850 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005851 if (bufSize >= 0 && bufSize < minBufSize)
5852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005853 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005854 return false;
5855 }
5856
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005857 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5858 {
5859 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5860 return false;
5861 }
5862
Jamie Madillbe849e42017-05-02 15:49:00 -04005863 switch (pname)
5864 {
5865 case GL_TEXTURE_WRAP_R:
5866 case GL_TEXTURE_SWIZZLE_R:
5867 case GL_TEXTURE_SWIZZLE_G:
5868 case GL_TEXTURE_SWIZZLE_B:
5869 case GL_TEXTURE_SWIZZLE_A:
5870 case GL_TEXTURE_BASE_LEVEL:
5871 case GL_TEXTURE_MAX_LEVEL:
5872 case GL_TEXTURE_COMPARE_MODE:
5873 case GL_TEXTURE_COMPARE_FUNC:
5874 case GL_TEXTURE_MIN_LOD:
5875 case GL_TEXTURE_MAX_LOD:
5876 if (context->getClientMajorVersion() < 3)
5877 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005878 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005879 return false;
5880 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005881 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005883 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5884 "available without "
5885 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005886 return false;
5887 }
5888 break;
5889
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005890 case GL_GENERATE_MIPMAP:
5891 case GL_TEXTURE_CROP_RECT_OES:
5892 if (context->getClientMajorVersion() > 1)
5893 {
5894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5895 return false;
5896 }
5897 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005898 default:
5899 break;
5900 }
5901
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005902 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005903 {
5904 switch (pname)
5905 {
5906 case GL_TEXTURE_MIN_FILTER:
5907 case GL_TEXTURE_MAG_FILTER:
5908 case GL_TEXTURE_WRAP_S:
5909 case GL_TEXTURE_WRAP_T:
5910 case GL_TEXTURE_WRAP_R:
5911 case GL_TEXTURE_MIN_LOD:
5912 case GL_TEXTURE_MAX_LOD:
5913 case GL_TEXTURE_COMPARE_MODE:
5914 case GL_TEXTURE_COMPARE_FUNC:
5915 context->handleError(InvalidEnum()
5916 << "Invalid parameter for 2D multisampled textures.");
5917 return false;
5918 }
5919 }
5920
Jamie Madillbe849e42017-05-02 15:49:00 -04005921 switch (pname)
5922 {
5923 case GL_TEXTURE_WRAP_S:
5924 case GL_TEXTURE_WRAP_T:
5925 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005926 {
5927 bool restrictedWrapModes =
5928 target == TextureType::External || target == TextureType::Rectangle;
5929 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005930 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005931 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005932 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005933 }
5934 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005935
5936 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005937 {
5938 bool restrictedMinFilter =
5939 target == TextureType::External || target == TextureType::Rectangle;
5940 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005941 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005942 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005943 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005944 }
5945 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005946
5947 case GL_TEXTURE_MAG_FILTER:
5948 if (!ValidateTextureMagFilterValue(context, params))
5949 {
5950 return false;
5951 }
5952 break;
5953
5954 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005955 if (!context->getExtensions().textureUsage)
5956 {
5957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5958 return false;
5959 }
5960
Jamie Madillbe849e42017-05-02 15:49:00 -04005961 switch (ConvertToGLenum(params[0]))
5962 {
5963 case GL_NONE:
5964 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5965 break;
5966
5967 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005968 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005969 return false;
5970 }
5971 break;
5972
5973 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005974 {
5975 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5976 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005977 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005978 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005979 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005980 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5981 }
5982 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005983
5984 case GL_TEXTURE_MIN_LOD:
5985 case GL_TEXTURE_MAX_LOD:
5986 // any value is permissible
5987 break;
5988
5989 case GL_TEXTURE_COMPARE_MODE:
5990 if (!ValidateTextureCompareModeValue(context, params))
5991 {
5992 return false;
5993 }
5994 break;
5995
5996 case GL_TEXTURE_COMPARE_FUNC:
5997 if (!ValidateTextureCompareFuncValue(context, params))
5998 {
5999 return false;
6000 }
6001 break;
6002
6003 case GL_TEXTURE_SWIZZLE_R:
6004 case GL_TEXTURE_SWIZZLE_G:
6005 case GL_TEXTURE_SWIZZLE_B:
6006 case GL_TEXTURE_SWIZZLE_A:
6007 switch (ConvertToGLenum(params[0]))
6008 {
6009 case GL_RED:
6010 case GL_GREEN:
6011 case GL_BLUE:
6012 case GL_ALPHA:
6013 case GL_ZERO:
6014 case GL_ONE:
6015 break;
6016
6017 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006018 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006019 return false;
6020 }
6021 break;
6022
6023 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006024 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006026 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006027 return false;
6028 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006029 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006030 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006031 context->handleError(InvalidOperation()
6032 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006033 return false;
6034 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006035 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006036 {
6037 context->handleError(InvalidOperation()
6038 << "Base level must be 0 for multisampled textures.");
6039 return false;
6040 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006041 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006042 {
6043 context->handleError(InvalidOperation()
6044 << "Base level must be 0 for rectangle textures.");
6045 return false;
6046 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006047 break;
6048
6049 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006050 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006051 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006052 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006053 return false;
6054 }
6055 break;
6056
6057 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6058 if (context->getClientVersion() < Version(3, 1))
6059 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006060 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006061 return false;
6062 }
6063 switch (ConvertToGLenum(params[0]))
6064 {
6065 case GL_DEPTH_COMPONENT:
6066 case GL_STENCIL_INDEX:
6067 break;
6068
6069 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006070 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006071 return false;
6072 }
6073 break;
6074
6075 case GL_TEXTURE_SRGB_DECODE_EXT:
6076 if (!ValidateTextureSRGBDecodeValue(context, params))
6077 {
6078 return false;
6079 }
6080 break;
6081
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006082 case GL_GENERATE_MIPMAP:
6083 case GL_TEXTURE_CROP_RECT_OES:
6084 if (context->getClientMajorVersion() > 1)
6085 {
6086 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6087 return false;
6088 }
6089 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006090 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006091 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006092 return false;
6093 }
6094
6095 return true;
6096}
6097
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006098template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6099template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006100
Jamie Madill5b772312018-03-08 20:28:32 -05006101bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006102{
6103 if (index >= MAX_VERTEX_ATTRIBS)
6104 {
6105 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6106 return false;
6107 }
6108
6109 return true;
6110}
6111
6112bool ValidateGetActiveUniformBlockivBase(Context *context,
6113 GLuint program,
6114 GLuint uniformBlockIndex,
6115 GLenum pname,
6116 GLsizei *length)
6117{
6118 if (length)
6119 {
6120 *length = 0;
6121 }
6122
6123 if (context->getClientMajorVersion() < 3)
6124 {
6125 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6126 return false;
6127 }
6128
6129 Program *programObject = GetValidProgram(context, program);
6130 if (!programObject)
6131 {
6132 return false;
6133 }
6134
6135 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6136 {
6137 context->handleError(InvalidValue()
6138 << "uniformBlockIndex exceeds active uniform block count.");
6139 return false;
6140 }
6141
6142 switch (pname)
6143 {
6144 case GL_UNIFORM_BLOCK_BINDING:
6145 case GL_UNIFORM_BLOCK_DATA_SIZE:
6146 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6147 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6148 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6149 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6150 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6151 break;
6152
6153 default:
6154 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6155 return false;
6156 }
6157
6158 if (length)
6159 {
6160 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6161 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006162 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006163 programObject->getUniformBlockByIndex(uniformBlockIndex);
6164 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6165 }
6166 else
6167 {
6168 *length = 1;
6169 }
6170 }
6171
6172 return true;
6173}
6174
Jamie Madill9696d072017-08-26 23:19:57 -04006175template <typename ParamType>
6176bool ValidateSamplerParameterBase(Context *context,
6177 GLuint sampler,
6178 GLenum pname,
6179 GLsizei bufSize,
6180 ParamType *params)
6181{
6182 if (context->getClientMajorVersion() < 3)
6183 {
6184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6185 return false;
6186 }
6187
6188 if (!context->isSampler(sampler))
6189 {
6190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6191 return false;
6192 }
6193
6194 const GLsizei minBufSize = 1;
6195 if (bufSize >= 0 && bufSize < minBufSize)
6196 {
6197 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6198 return false;
6199 }
6200
6201 switch (pname)
6202 {
6203 case GL_TEXTURE_WRAP_S:
6204 case GL_TEXTURE_WRAP_T:
6205 case GL_TEXTURE_WRAP_R:
6206 if (!ValidateTextureWrapModeValue(context, params, false))
6207 {
6208 return false;
6209 }
6210 break;
6211
6212 case GL_TEXTURE_MIN_FILTER:
6213 if (!ValidateTextureMinFilterValue(context, params, false))
6214 {
6215 return false;
6216 }
6217 break;
6218
6219 case GL_TEXTURE_MAG_FILTER:
6220 if (!ValidateTextureMagFilterValue(context, params))
6221 {
6222 return false;
6223 }
6224 break;
6225
6226 case GL_TEXTURE_MIN_LOD:
6227 case GL_TEXTURE_MAX_LOD:
6228 // any value is permissible
6229 break;
6230
6231 case GL_TEXTURE_COMPARE_MODE:
6232 if (!ValidateTextureCompareModeValue(context, params))
6233 {
6234 return false;
6235 }
6236 break;
6237
6238 case GL_TEXTURE_COMPARE_FUNC:
6239 if (!ValidateTextureCompareFuncValue(context, params))
6240 {
6241 return false;
6242 }
6243 break;
6244
6245 case GL_TEXTURE_SRGB_DECODE_EXT:
6246 if (!ValidateTextureSRGBDecodeValue(context, params))
6247 {
6248 return false;
6249 }
6250 break;
6251
Luc Ferron1b1a8642018-01-23 15:12:01 -05006252 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6253 {
6254 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6255 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6256 {
6257 return false;
6258 }
6259 }
6260 break;
6261
Jamie Madill9696d072017-08-26 23:19:57 -04006262 default:
6263 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6264 return false;
6265 }
6266
6267 return true;
6268}
6269
6270template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6271template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6272
6273bool ValidateGetSamplerParameterBase(Context *context,
6274 GLuint sampler,
6275 GLenum pname,
6276 GLsizei *length)
6277{
6278 if (length)
6279 {
6280 *length = 0;
6281 }
6282
6283 if (context->getClientMajorVersion() < 3)
6284 {
6285 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6286 return false;
6287 }
6288
6289 if (!context->isSampler(sampler))
6290 {
6291 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6292 return false;
6293 }
6294
6295 switch (pname)
6296 {
6297 case GL_TEXTURE_WRAP_S:
6298 case GL_TEXTURE_WRAP_T:
6299 case GL_TEXTURE_WRAP_R:
6300 case GL_TEXTURE_MIN_FILTER:
6301 case GL_TEXTURE_MAG_FILTER:
6302 case GL_TEXTURE_MIN_LOD:
6303 case GL_TEXTURE_MAX_LOD:
6304 case GL_TEXTURE_COMPARE_MODE:
6305 case GL_TEXTURE_COMPARE_FUNC:
6306 break;
6307
Luc Ferron1b1a8642018-01-23 15:12:01 -05006308 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6309 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6310 {
6311 return false;
6312 }
6313 break;
6314
Jamie Madill9696d072017-08-26 23:19:57 -04006315 case GL_TEXTURE_SRGB_DECODE_EXT:
6316 if (!context->getExtensions().textureSRGBDecode)
6317 {
6318 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6319 return false;
6320 }
6321 break;
6322
6323 default:
6324 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6325 return false;
6326 }
6327
6328 if (length)
6329 {
6330 *length = 1;
6331 }
6332 return true;
6333}
6334
6335bool ValidateGetInternalFormativBase(Context *context,
6336 GLenum target,
6337 GLenum internalformat,
6338 GLenum pname,
6339 GLsizei bufSize,
6340 GLsizei *numParams)
6341{
6342 if (numParams)
6343 {
6344 *numParams = 0;
6345 }
6346
6347 if (context->getClientMajorVersion() < 3)
6348 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006349 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006350 return false;
6351 }
6352
6353 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006354 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006355 {
6356 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6357 return false;
6358 }
6359
6360 switch (target)
6361 {
6362 case GL_RENDERBUFFER:
6363 break;
6364
6365 case GL_TEXTURE_2D_MULTISAMPLE:
6366 if (context->getClientVersion() < ES_3_1)
6367 {
6368 context->handleError(InvalidOperation()
6369 << "Texture target requires at least OpenGL ES 3.1.");
6370 return false;
6371 }
6372 break;
6373
6374 default:
6375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6376 return false;
6377 }
6378
6379 if (bufSize < 0)
6380 {
6381 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6382 return false;
6383 }
6384
6385 GLsizei maxWriteParams = 0;
6386 switch (pname)
6387 {
6388 case GL_NUM_SAMPLE_COUNTS:
6389 maxWriteParams = 1;
6390 break;
6391
6392 case GL_SAMPLES:
6393 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6394 break;
6395
6396 default:
6397 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6398 return false;
6399 }
6400
6401 if (numParams)
6402 {
6403 // glGetInternalFormativ will not overflow bufSize
6404 *numParams = std::min(bufSize, maxWriteParams);
6405 }
6406
6407 return true;
6408}
6409
Jamie Madille98b1b52018-03-08 09:47:23 -05006410bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6411{
Jamie Madill427064d2018-04-13 16:20:34 -04006412 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006413 {
6414 context->handleError(InvalidOperation());
6415 return false;
6416 }
6417 return true;
6418}
6419
Lingfeng Yang038dd532018-03-29 17:31:52 -07006420bool ValidateMultitextureUnit(Context *context, GLenum texture)
6421{
6422 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6423 {
6424 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6425 return false;
6426 }
6427 return true;
6428}
6429
Jamie Madillc29968b2016-01-20 11:17:23 -05006430} // namespace gl