blob: 2b68e5b13190c6667b4200177630169c7b315bf0 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Lingfeng Yangf97641c2018-06-21 19:22:45 -070025#include "libANGLE/queryutils.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040026#include "libANGLE/validationES2.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29#include "common/mathutil.h"
30#include "common/utilities.h"
31
Jamie Madille2e406c2016-06-02 13:04:10 -040032using namespace angle;
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034namespace gl
35{
Jamie Madill1ca74672015-07-21 15:14:11 -040036namespace
37{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050038bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
39{
40 // List of compressed format that require that the texture size is smaller than or a multiple of
41 // the compressed block size.
42 switch (internalFormat)
43 {
44 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
46 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
47 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
48 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
52 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
53 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59 return true;
jchen10a99ed552017-09-22 08:10:32 +080060
Luc Ferron9dbaeba2018-02-01 07:26:59 -050061 default:
62 return false;
63 }
64}
65bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
66{
67 // Compressed sub textures have additional formats that requires exact size.
68 // ES 3.1, Section 8.7, Page 171
69 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
70 IsETC2EACFormat(internalFormat);
71}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030072
73bool DifferenceCanOverflow(GLint a, GLint b)
74{
75 CheckedNumeric<GLint> checkedA(a);
76 checkedA -= b;
77 // Use negation to make sure that the difference can't overflow regardless of the order.
78 checkedA = -checkedA;
79 return !checkedA.IsValid();
80}
81
Jamie Madillac43aaa2018-07-31 11:22:13 -040082bool ValidateDrawClientAttribs(Context *context)
83{
Jamie Madill2da53562018-08-01 11:34:47 -040084 ASSERT(context->getStateCache().hasAnyEnabledClientAttrib());
Jamie Madillac43aaa2018-07-31 11:22:13 -040085
Jamie Madill43da7c42018-08-01 11:34:49 -040086 const State &state = context->getGLState();
Jamie Madillac43aaa2018-07-31 11:22:13 -040087
88 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
89 {
90 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
91 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
92 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
93 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
94 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
95 return false;
96 }
97
98 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
99 {
100 // This is an application error that would normally result in a crash, but we catch it
101 // and return an error
102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
103 return false;
104 }
105
106 return true;
107}
108
Jamie Madill2da53562018-08-01 11:34:47 -0400109bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -0400110{
Jamie Madill51af38b2018-04-15 08:50:56 -0400111 // If we're drawing zero vertices, we have enough data.
Jamie Madill2da53562018-08-01 11:34:47 -0400112 ASSERT(primcount > 0);
Jamie Madill51af38b2018-04-15 08:50:56 -0400113
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400114 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
115 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
Jamie Madill1ca74672015-07-21 15:14:11 -0400116 {
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400117 return true;
Jamie Madill02c9c042018-04-17 13:43:48 -0400118 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800119
Jamie 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
Jamie Madill43da7c42018-08-01 11:34:49 -0400776 return level <= 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 Madill43da7c42018-08-01 11:34:49 -0400797 (level != 0 && (!isPow2(width) || !isPow2(height) || !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{
Jamie Madill43da7c42018-08-01 11:34:49 -0400824 const InternalFormat &formatInfo = 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{
Jamie Madill43da7c42018-08-01 11:34:49 -0400863 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400864 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{
Jamie Madill43da7c42018-08-01 11:34:49 -0400908 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400909 if (pixelUnpackBuffer == nullptr && imageSize < 0)
910 {
911 // Checks are not required
912 return true;
913 }
914
915 // ...the data would be unpacked from the buffer object such that the memory reads required
916 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400917 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400918 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400919 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400920 const auto &unpack = context->getGLState().getUnpackState();
921
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800922 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400923 GLuint endByte = 0;
924 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400925 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400926 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400927 return false;
928 }
929
Geoff Langff5b2d52016-09-07 11:32:23 -0400930 if (pixelUnpackBuffer)
931 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400932 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400933 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
934 checkedEndByte += checkedOffset;
935
936 if (!checkedEndByte.IsValid() ||
937 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
938 {
939 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400941 return false;
942 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800943 if (context->getExtensions().webglCompatibility &&
944 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
945 {
946 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
947 PixelUnpackBufferBoundForTransformFeedback);
948 return false;
949 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400950 }
951 else
952 {
953 ASSERT(imageSize >= 0);
954 if (pixels == nullptr && imageSize != 0)
955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500956 context->handleError(InvalidOperation()
957 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400958 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400959 }
960
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400961 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500963 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400964 return false;
965 }
966 }
967
968 return true;
969}
970
Corentin Wallezad3ae902018-03-09 13:40:42 -0500971bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500972{
Geoff Lang37dde692014-01-31 16:34:54 -0500973 switch (queryType)
974 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500975 case QueryType::AnySamples:
976 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400977 return context->getClientMajorVersion() >= 3 ||
978 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500979 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800980 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500981 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500983 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800984 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500985 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800986 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800987 default:
988 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500989 }
990}
991
Jamie Madill5b772312018-03-08 20:28:32 -0500992bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400993 GLenum type,
994 GLboolean normalized,
995 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400996 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400997 bool pureInteger)
998{
999 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001000 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1001 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1002 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1003 // parameter exceeds 255.
1004 constexpr GLsizei kMaxWebGLStride = 255;
1005 if (stride > kMaxWebGLStride)
1006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001007 context->handleError(InvalidValue()
1008 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001009 return false;
1010 }
1011
1012 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1013 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1014 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1015 // or an INVALID_OPERATION error is generated.
1016 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1017 size_t typeSize = GetVertexFormatTypeSize(internalType);
1018
1019 ASSERT(isPow2(typeSize) && typeSize > 0);
1020 size_t sizeMask = (typeSize - 1);
1021 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1022 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001023 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001024 return false;
1025 }
1026
1027 if ((stride & sizeMask) != 0)
1028 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001029 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001030 return false;
1031 }
1032
1033 return true;
1034}
1035
Jamie Madill5b772312018-03-08 20:28:32 -05001036Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001037{
He Yunchaoced53ae2016-11-29 15:00:51 +08001038 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1039 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1040 // or program object and INVALID_OPERATION if the provided name identifies an object
1041 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001042
Dian Xiang769769a2015-09-09 15:20:08 -07001043 Program *validProgram = context->getProgram(id);
1044
1045 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001046 {
Dian Xiang769769a2015-09-09 15:20:08 -07001047 if (context->getShader(id))
1048 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001049 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001050 }
1051 else
1052 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001053 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001054 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001055 }
Dian Xiang769769a2015-09-09 15:20:08 -07001056
1057 return validProgram;
1058}
1059
Jamie Madill5b772312018-03-08 20:28:32 -05001060Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001061{
1062 // See ValidProgram for spec details.
1063
1064 Shader *validShader = context->getShader(id);
1065
1066 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001067 {
Dian Xiang769769a2015-09-09 15:20:08 -07001068 if (context->getProgram(id))
1069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001071 }
1072 else
1073 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001074 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001075 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001076 }
Dian Xiang769769a2015-09-09 15:20:08 -07001077
1078 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001079}
1080
Jamie Madill43da7c42018-08-01 11:34:49 -04001081bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001082{
Geoff Langfa125c92017-10-24 13:01:46 -04001083 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001084 {
Geoff Langfa125c92017-10-24 13:01:46 -04001085 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1086 {
1087 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1088 return false;
1089 }
Jamie Madillb4472272014-07-03 10:38:55 -04001090
Geoff Langfa125c92017-10-24 13:01:46 -04001091 // Color attachment 0 is validated below because it is always valid
1092 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001093 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001094 {
Geoff Langfa125c92017-10-24 13:01:46 -04001095 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001096 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001097 }
1098 }
1099 else
1100 {
1101 switch (attachment)
1102 {
Geoff Langfa125c92017-10-24 13:01:46 -04001103 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001104 case GL_DEPTH_ATTACHMENT:
1105 case GL_STENCIL_ATTACHMENT:
1106 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001107
He Yunchaoced53ae2016-11-29 15:00:51 +08001108 case GL_DEPTH_STENCIL_ATTACHMENT:
1109 if (!context->getExtensions().webglCompatibility &&
1110 context->getClientMajorVersion() < 3)
1111 {
Geoff Langfa125c92017-10-24 13:01:46 -04001112 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001113 return false;
1114 }
1115 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001116
He Yunchaoced53ae2016-11-29 15:00:51 +08001117 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001118 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001119 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001120 }
1121 }
1122
1123 return true;
1124}
1125
Jamie Madill5b772312018-03-08 20:28:32 -05001126bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001127 GLenum target,
1128 GLsizei samples,
1129 GLenum internalformat,
1130 GLsizei width,
1131 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001132{
1133 switch (target)
1134 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001135 case GL_RENDERBUFFER:
1136 break;
1137 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001138 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001139 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001140 }
1141
1142 if (width < 0 || height < 0 || samples < 0)
1143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001144 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001145 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001146 }
1147
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001148 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1149 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1150
1151 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001152 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001154 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001155 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001156 }
1157
1158 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1159 // 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 -08001160 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001161 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001162 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001163 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001164 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001165 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001166 }
1167
Geoff Langaae65a42014-05-26 12:43:44 -04001168 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001171 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001172 }
1173
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001174 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001175 if (handle == 0)
1176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001177 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001178 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001179 }
1180
1181 return true;
1182}
1183
Jamie Madill43da7c42018-08-01 11:34:49 -04001184bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001185 GLenum target,
1186 GLenum attachment,
1187 GLenum renderbuffertarget,
1188 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001189{
Geoff Lange8afa902017-09-27 15:00:43 -04001190 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001192 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001193 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001194 }
1195
Jamie Madill43da7c42018-08-01 11:34:49 -04001196 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001197
Jamie Madill84115c92015-04-23 15:00:07 -04001198 ASSERT(framebuffer);
1199 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001200 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001201 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001202 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001203 }
1204
Jamie Madillb4472272014-07-03 10:38:55 -04001205 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001206 {
Jamie Madillb4472272014-07-03 10:38:55 -04001207 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001208 }
1209
Jamie Madillab9d82c2014-01-21 16:38:14 -05001210 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1211 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1212 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1213 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1214 if (renderbuffer != 0)
1215 {
1216 if (!context->getRenderbuffer(renderbuffer))
1217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001219 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001220 }
1221 }
1222
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001223 return true;
1224}
1225
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001226bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001227 GLint srcX0,
1228 GLint srcY0,
1229 GLint srcX1,
1230 GLint srcY1,
1231 GLint dstX0,
1232 GLint dstY0,
1233 GLint dstX1,
1234 GLint dstY1,
1235 GLbitfield mask,
1236 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001237{
1238 switch (filter)
1239 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001240 case GL_NEAREST:
1241 break;
1242 case GL_LINEAR:
1243 break;
1244 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001245 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001246 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247 }
1248
1249 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001251 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001252 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001253 }
1254
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001255 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1256 // color buffer, leaving only nearest being unfiltered from above
1257 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1258 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001259 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001260 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261 }
1262
Jamie Madill51f40ec2016-06-15 14:06:00 -04001263 const auto &glState = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04001264 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1265 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001266
1267 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001269 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001270 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271 }
1272
Jamie Madill427064d2018-04-13 16:20:34 -04001273 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001274 {
Jamie Madill48faf802014-11-06 15:27:22 -05001275 return false;
1276 }
1277
Jamie Madill427064d2018-04-13 16:20:34 -04001278 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001279 {
Jamie Madill48faf802014-11-06 15:27:22 -05001280 return false;
1281 }
1282
Qin Jiajiaaef92162018-02-27 13:51:44 +08001283 if (readFramebuffer->id() == drawFramebuffer->id())
1284 {
1285 context->handleError(InvalidOperation());
1286 return false;
1287 }
1288
Jamie Madille98b1b52018-03-08 09:47:23 -05001289 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001290 {
Geoff Langb1196682014-07-23 13:47:29 -04001291 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001292 }
1293
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001294 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1295 // always run it in order to avoid triggering driver bugs.
1296 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1297 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001298 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001299 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1300 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001301 }
1302
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001303 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1304
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305 if (mask & GL_COLOR_BUFFER_BIT)
1306 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001307 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001308 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001309
He Yunchao66a41a22016-12-15 16:45:05 +08001310 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001311 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001312 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001313
Geoff Langa15472a2015-08-11 11:48:03 -04001314 for (size_t drawbufferIdx = 0;
1315 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001316 {
Geoff Langa15472a2015-08-11 11:48:03 -04001317 const FramebufferAttachment *attachment =
1318 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1319 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001321 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001322
Geoff Langb2f3d052013-08-13 12:49:27 -04001323 // The GL ES 3.0.2 spec (pg 193) states that:
1324 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001325 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1326 // as well
1327 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1328 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001329 // Changes with EXT_color_buffer_float:
1330 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001331 GLenum readComponentType = readFormat.info->componentType;
1332 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001333 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001334 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001335 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001336 drawComponentType == GL_SIGNED_NORMALIZED);
1337
1338 if (extensions.colorBufferFloat)
1339 {
1340 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1341 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1342
1343 if (readFixedOrFloat != drawFixedOrFloat)
1344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001345 context->handleError(InvalidOperation()
1346 << "If the read buffer contains fixed-point or "
1347 "floating-point values, the draw buffer must "
1348 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001349 return false;
1350 }
1351 }
1352 else if (readFixedPoint != drawFixedPoint)
1353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001354 context->handleError(InvalidOperation()
1355 << "If the read buffer contains fixed-point values, "
1356 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001357 return false;
1358 }
1359
1360 if (readComponentType == GL_UNSIGNED_INT &&
1361 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001364 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 }
1366
Jamie Madill6163c752015-12-07 16:32:59 -05001367 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001369 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001370 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 }
1372
Jamie Madilla3944d42016-07-22 22:13:26 -04001373 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001374 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001376 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001377 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001378 }
Geoff Lange4915782017-04-12 15:19:07 -04001379
1380 if (context->getExtensions().webglCompatibility &&
1381 *readColorBuffer == *attachment)
1382 {
1383 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001384 InvalidOperation()
1385 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001386 return false;
1387 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 }
1389 }
1390
Jamie Madilla3944d42016-07-22 22:13:26 -04001391 if ((readFormat.info->componentType == GL_INT ||
1392 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1393 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001395 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001396 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 }
He Yunchao66a41a22016-12-15 16:45:05 +08001399 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1400 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1401 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1402 // situation is an application error that would lead to a crash in ANGLE.
1403 else if (drawFramebuffer->hasEnabledDrawBuffer())
1404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(
1406 InvalidOperation()
1407 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001408 return false;
1409 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410 }
1411
He Yunchaoced53ae2016-11-29 15:00:51 +08001412 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001413 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1414 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001415 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001416 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001418 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001419 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001420 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001421 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001423 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424 {
Kenneth Russell69382852017-07-21 16:38:44 -04001425 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001427 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001428 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001429 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001431 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001434 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 }
Geoff Lange4915782017-04-12 15:19:07 -04001436
1437 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001439 context->handleError(
1440 InvalidOperation()
1441 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001442 return false;
1443 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001444 }
He Yunchao66a41a22016-12-15 16:45:05 +08001445 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1446 else if (drawBuffer)
1447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001448 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1449 "depth/stencil attachment of a "
1450 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001451 return false;
1452 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001453 }
1454 }
1455
Martin Radeva3ed4572017-07-27 18:29:37 +03001456 // ANGLE_multiview, Revision 1:
1457 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001458 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1459 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1460 // views in the current read framebuffer is more than one.
1461 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001462 {
1463 context->handleError(InvalidFramebufferOperation()
1464 << "Attempt to read from a multi-view framebuffer.");
1465 return false;
1466 }
1467 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1468 {
1469 context->handleError(InvalidFramebufferOperation()
1470 << "Attempt to write to a multi-view framebuffer.");
1471 return false;
1472 }
1473
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001474 return true;
1475}
1476
Jamie Madill4928b7c2017-06-20 12:57:39 -04001477bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001478 GLint x,
1479 GLint y,
1480 GLsizei width,
1481 GLsizei height,
1482 GLenum format,
1483 GLenum type,
1484 GLsizei bufSize,
1485 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001486 GLsizei *columns,
1487 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001488 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001489{
1490 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001491 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001492 return false;
1493 }
1494
Brandon Jonesd1049182018-03-28 10:02:20 -07001495 GLsizei writeLength = 0;
1496 GLsizei writeColumns = 0;
1497 GLsizei writeRows = 0;
1498
1499 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1500 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001501 {
Geoff Langb1196682014-07-23 13:47:29 -04001502 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001503 }
1504
Brandon Jonesd1049182018-03-28 10:02:20 -07001505 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001506 {
Geoff Langb1196682014-07-23 13:47:29 -04001507 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001508 }
1509
Brandon Jonesd1049182018-03-28 10:02:20 -07001510 SetRobustLengthParam(length, writeLength);
1511 SetRobustLengthParam(columns, writeColumns);
1512 SetRobustLengthParam(rows, writeRows);
1513
Jamie Madillc29968b2016-01-20 11:17:23 -05001514 return true;
1515}
1516
1517bool ValidateReadnPixelsEXT(Context *context,
1518 GLint x,
1519 GLint y,
1520 GLsizei width,
1521 GLsizei height,
1522 GLenum format,
1523 GLenum type,
1524 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001525 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001526{
1527 if (bufSize < 0)
1528 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001529 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001530 return false;
1531 }
1532
Geoff Lang62fce5b2016-09-30 10:46:35 -04001533 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001534 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001535}
Jamie Madill26e91952014-03-05 15:01:27 -05001536
Jamie Madill4928b7c2017-06-20 12:57:39 -04001537bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001538 GLint x,
1539 GLint y,
1540 GLsizei width,
1541 GLsizei height,
1542 GLenum format,
1543 GLenum type,
1544 GLsizei bufSize,
1545 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001546 GLsizei *columns,
1547 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001548 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001549{
Brandon Jonesd1049182018-03-28 10:02:20 -07001550 GLsizei writeLength = 0;
1551 GLsizei writeColumns = 0;
1552 GLsizei writeRows = 0;
1553
Geoff Lang62fce5b2016-09-30 10:46:35 -04001554 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001555 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001556 return false;
1557 }
1558
Brandon Jonesd1049182018-03-28 10:02:20 -07001559 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1560 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001561 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001562 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001563 }
1564
Brandon Jonesd1049182018-03-28 10:02:20 -07001565 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001566 {
1567 return false;
1568 }
1569
Brandon Jonesd1049182018-03-28 10:02:20 -07001570 SetRobustLengthParam(length, writeLength);
1571 SetRobustLengthParam(columns, writeColumns);
1572 SetRobustLengthParam(rows, writeRows);
1573
Geoff Lang62fce5b2016-09-30 10:46:35 -04001574 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001575}
1576
Jamie Madill43da7c42018-08-01 11:34:49 -04001577bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001578{
1579 if (!context->getExtensions().occlusionQueryBoolean &&
1580 !context->getExtensions().disjointTimerQuery)
1581 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001582 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001583 return false;
1584 }
1585
Olli Etuaho41997e72016-03-10 13:38:39 +02001586 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001587}
1588
Jamie Madill43da7c42018-08-01 11:34:49 -04001589bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001590{
1591 if (!context->getExtensions().occlusionQueryBoolean &&
1592 !context->getExtensions().disjointTimerQuery)
1593 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001594 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001595 return false;
1596 }
1597
Olli Etuaho41997e72016-03-10 13:38:39 +02001598 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001599}
1600
Jamie Madill43da7c42018-08-01 11:34:49 -04001601bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001602{
1603 if (!context->getExtensions().occlusionQueryBoolean &&
1604 !context->getExtensions().disjointTimerQuery)
1605 {
1606 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1607 return false;
1608 }
1609
1610 return true;
1611}
1612
Jamie Madill43da7c42018-08-01 11:34:49 -04001613bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001614{
1615 if (!ValidQueryType(context, target))
1616 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001617 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001618 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001619 }
1620
1621 if (id == 0)
1622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001623 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001624 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001625 }
1626
1627 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1628 // of zero, if the active query object name for <target> is non-zero (for the
1629 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1630 // the active query for either target is non-zero), if <id> is the name of an
1631 // existing query object whose type does not match <target>, or if <id> is the
1632 // active query object name for any query type, the error INVALID_OPERATION is
1633 // generated.
1634
1635 // Ensure no other queries are active
1636 // NOTE: If other queries than occlusion are supported, we will need to check
1637 // separately that:
1638 // a) The query ID passed is not the current active query for any target/type
1639 // b) There are no active queries for the requested target (and in the case
1640 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1641 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001642
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001643 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001645 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001646 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001647 }
1648
1649 Query *queryObject = context->getQuery(id, true, target);
1650
1651 // check that name was obtained with glGenQueries
1652 if (!queryObject)
1653 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001655 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001656 }
1657
1658 // check for type mismatch
1659 if (queryObject->getType() != target)
1660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001661 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001662 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001663 }
1664
1665 return true;
1666}
1667
Jamie Madill43da7c42018-08-01 11:34:49 -04001668bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001669{
1670 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001671 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001672 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001674 return false;
1675 }
1676
1677 return ValidateBeginQueryBase(context, target, id);
1678}
1679
Jamie Madill43da7c42018-08-01 11:34:49 -04001680bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001681{
1682 if (!ValidQueryType(context, target))
1683 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001684 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001685 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001686 }
1687
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001688 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001689
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001690 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001692 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001693 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001694 }
1695
Jamie Madill45c785d2014-05-13 14:09:34 -04001696 return true;
1697}
1698
Jamie Madill43da7c42018-08-01 11:34:49 -04001699bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700{
1701 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001702 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001703 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001704 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 return false;
1706 }
1707
1708 return ValidateEndQueryBase(context, target);
1709}
1710
Corentin Wallezad3ae902018-03-09 13:40:42 -05001711bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001712{
1713 if (!context->getExtensions().disjointTimerQuery)
1714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001715 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001716 return false;
1717 }
1718
Corentin Wallezad3ae902018-03-09 13:40:42 -05001719 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001720 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001721 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 return false;
1723 }
1724
1725 Query *queryObject = context->getQuery(id, true, target);
1726 if (queryObject == nullptr)
1727 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001728 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001729 return false;
1730 }
1731
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001732 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001733 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001734 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001735 return false;
1736 }
1737
1738 return true;
1739}
1740
Corentin Wallezad3ae902018-03-09 13:40:42 -05001741bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001742{
Geoff Lang2186c382016-10-14 10:54:54 -04001743 if (numParams)
1744 {
1745 *numParams = 0;
1746 }
1747
Corentin Wallezad3ae902018-03-09 13:40:42 -05001748 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001749 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001750 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001751 return false;
1752 }
1753
1754 switch (pname)
1755 {
1756 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001757 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001759 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001760 return false;
1761 }
1762 break;
1763 case GL_QUERY_COUNTER_BITS_EXT:
1764 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001765 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001766 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001767 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001768 return false;
1769 }
1770 break;
1771 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001772 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001773 return false;
1774 }
1775
Geoff Lang2186c382016-10-14 10:54:54 -04001776 if (numParams)
1777 {
1778 // All queries return only one value
1779 *numParams = 1;
1780 }
1781
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001782 return true;
1783}
1784
Corentin Wallezad3ae902018-03-09 13:40:42 -05001785bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001786{
1787 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001788 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001789 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001790 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001791 return false;
1792 }
1793
Geoff Lang2186c382016-10-14 10:54:54 -04001794 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001795}
1796
Geoff Lang2186c382016-10-14 10:54:54 -04001797bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001798 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001799 GLenum pname,
1800 GLsizei bufSize,
1801 GLsizei *length,
1802 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001803{
Geoff Lang2186c382016-10-14 10:54:54 -04001804 if (!ValidateRobustEntryPoint(context, bufSize))
1805 {
1806 return false;
1807 }
1808
Brandon Jonesd1049182018-03-28 10:02:20 -07001809 GLsizei numParams = 0;
1810
1811 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001812 {
1813 return false;
1814 }
1815
Brandon Jonesd1049182018-03-28 10:02:20 -07001816 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001817 {
1818 return false;
1819 }
1820
Brandon Jonesd1049182018-03-28 10:02:20 -07001821 SetRobustLengthParam(length, numParams);
1822
Geoff Lang2186c382016-10-14 10:54:54 -04001823 return true;
1824}
1825
1826bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1827{
1828 if (numParams)
1829 {
1830 *numParams = 0;
1831 }
1832
Corentin Wallezad3ae902018-03-09 13:40:42 -05001833 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001834
1835 if (!queryObject)
1836 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001837 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001838 return false;
1839 }
1840
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001841 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001842 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001843 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001844 return false;
1845 }
1846
1847 switch (pname)
1848 {
1849 case GL_QUERY_RESULT_EXT:
1850 case GL_QUERY_RESULT_AVAILABLE_EXT:
1851 break;
1852
1853 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001854 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001855 return false;
1856 }
1857
Geoff Lang2186c382016-10-14 10:54:54 -04001858 if (numParams)
1859 {
1860 *numParams = 1;
1861 }
1862
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001863 return true;
1864}
1865
1866bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1867{
1868 if (!context->getExtensions().disjointTimerQuery)
1869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001870 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001871 return false;
1872 }
Geoff Lang2186c382016-10-14 10:54:54 -04001873 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1874}
1875
1876bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1877 GLuint id,
1878 GLenum pname,
1879 GLsizei bufSize,
1880 GLsizei *length,
1881 GLint *params)
1882{
1883 if (!context->getExtensions().disjointTimerQuery)
1884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001885 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001886 return false;
1887 }
1888
1889 if (!ValidateRobustEntryPoint(context, bufSize))
1890 {
1891 return false;
1892 }
1893
Brandon Jonesd1049182018-03-28 10:02:20 -07001894 GLsizei numParams = 0;
1895
1896 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001897 {
1898 return false;
1899 }
1900
Brandon Jonesd1049182018-03-28 10:02:20 -07001901 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001902 {
1903 return false;
1904 }
1905
Brandon Jonesd1049182018-03-28 10:02:20 -07001906 SetRobustLengthParam(length, numParams);
1907
Geoff Lang2186c382016-10-14 10:54:54 -04001908 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001909}
1910
1911bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1912{
1913 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001914 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001915 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001916 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001917 return false;
1918 }
Geoff Lang2186c382016-10-14 10:54:54 -04001919 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1920}
1921
1922bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1923 GLuint id,
1924 GLenum pname,
1925 GLsizei bufSize,
1926 GLsizei *length,
1927 GLuint *params)
1928{
1929 if (!context->getExtensions().disjointTimerQuery &&
1930 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001932 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001933 return false;
1934 }
1935
1936 if (!ValidateRobustEntryPoint(context, bufSize))
1937 {
1938 return false;
1939 }
1940
Brandon Jonesd1049182018-03-28 10:02:20 -07001941 GLsizei numParams = 0;
1942
1943 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001944 {
1945 return false;
1946 }
1947
Brandon Jonesd1049182018-03-28 10:02:20 -07001948 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001949 {
1950 return false;
1951 }
1952
Brandon Jonesd1049182018-03-28 10:02:20 -07001953 SetRobustLengthParam(length, numParams);
1954
Geoff Lang2186c382016-10-14 10:54:54 -04001955 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001956}
1957
1958bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1959{
1960 if (!context->getExtensions().disjointTimerQuery)
1961 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001962 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001963 return false;
1964 }
Geoff Lang2186c382016-10-14 10:54:54 -04001965 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1966}
1967
1968bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1969 GLuint id,
1970 GLenum pname,
1971 GLsizei bufSize,
1972 GLsizei *length,
1973 GLint64 *params)
1974{
1975 if (!context->getExtensions().disjointTimerQuery)
1976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001978 return false;
1979 }
1980
1981 if (!ValidateRobustEntryPoint(context, bufSize))
1982 {
1983 return false;
1984 }
1985
Brandon Jonesd1049182018-03-28 10:02:20 -07001986 GLsizei numParams = 0;
1987
1988 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001989 {
1990 return false;
1991 }
1992
Brandon Jonesd1049182018-03-28 10:02:20 -07001993 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001994 {
1995 return false;
1996 }
1997
Brandon Jonesd1049182018-03-28 10:02:20 -07001998 SetRobustLengthParam(length, numParams);
1999
Geoff Lang2186c382016-10-14 10:54:54 -04002000 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002001}
2002
2003bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2004{
2005 if (!context->getExtensions().disjointTimerQuery)
2006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002008 return false;
2009 }
Geoff Lang2186c382016-10-14 10:54:54 -04002010 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2011}
2012
2013bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2014 GLuint id,
2015 GLenum pname,
2016 GLsizei bufSize,
2017 GLsizei *length,
2018 GLuint64 *params)
2019{
2020 if (!context->getExtensions().disjointTimerQuery)
2021 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002022 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002023 return false;
2024 }
2025
2026 if (!ValidateRobustEntryPoint(context, bufSize))
2027 {
2028 return false;
2029 }
2030
Brandon Jonesd1049182018-03-28 10:02:20 -07002031 GLsizei numParams = 0;
2032
2033 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002034 {
2035 return false;
2036 }
2037
Brandon Jonesd1049182018-03-28 10:02:20 -07002038 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002039 {
2040 return false;
2041 }
2042
Brandon Jonesd1049182018-03-28 10:02:20 -07002043 SetRobustLengthParam(length, numParams);
2044
Geoff Lang2186c382016-10-14 10:54:54 -04002045 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002046}
2047
Jamie Madill5b772312018-03-08 20:28:32 -05002048bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002049 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002050 GLint location,
2051 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002052 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002053{
Jiajia Qin5451d532017-11-16 17:16:34 +08002054 // TODO(Jiajia): Add image uniform check in future.
2055 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002056 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002057 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002058 return false;
2059 }
2060
Jiajia Qin5451d532017-11-16 17:16:34 +08002061 if (!program)
2062 {
2063 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2064 return false;
2065 }
2066
2067 if (!program->isLinked())
2068 {
2069 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2070 return false;
2071 }
2072
2073 if (location == -1)
2074 {
2075 // Silently ignore the uniform command
2076 return false;
2077 }
2078
2079 const auto &uniformLocations = program->getUniformLocations();
2080 size_t castedLocation = static_cast<size_t>(location);
2081 if (castedLocation >= uniformLocations.size())
2082 {
2083 context->handleError(InvalidOperation() << "Invalid uniform location");
2084 return false;
2085 }
2086
2087 const auto &uniformLocation = uniformLocations[castedLocation];
2088 if (uniformLocation.ignored)
2089 {
2090 // Silently ignore the uniform command
2091 return false;
2092 }
2093
2094 if (!uniformLocation.used())
2095 {
2096 context->handleError(InvalidOperation());
2097 return false;
2098 }
2099
2100 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2101
2102 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002103 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002104 {
2105 context->handleError(InvalidOperation());
2106 return false;
2107 }
2108
2109 *uniformOut = &uniform;
2110 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002111}
2112
Jamie Madill5b772312018-03-08 20:28:32 -05002113bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002114 GLenum uniformType,
2115 GLsizei count,
2116 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002117{
Jiajia Qin5451d532017-11-16 17:16:34 +08002118 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2119 // It is compatible with INT or BOOL.
2120 // Do these cheap tests first, for a little extra speed.
2121 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002122 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002123 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002124 }
2125
Jiajia Qin5451d532017-11-16 17:16:34 +08002126 if (IsSamplerType(uniformType))
2127 {
2128 // Check that the values are in range.
2129 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2130 for (GLsizei i = 0; i < count; ++i)
2131 {
2132 if (value[i] < 0 || value[i] >= max)
2133 {
2134 context->handleError(InvalidValue() << "sampler uniform value out of range");
2135 return false;
2136 }
2137 }
2138 return true;
2139 }
2140
2141 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2142 return false;
2143}
2144
Jamie Madill5b772312018-03-08 20:28:32 -05002145bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002146{
2147 // Check that the value type is compatible with uniform type.
2148 // Do the cheaper test first, for a little extra speed.
2149 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2150 {
2151 return true;
2152 }
2153
2154 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2155 return false;
2156}
2157
Jamie Madill5b772312018-03-08 20:28:32 -05002158bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002159{
2160 // Check that the value type is compatible with uniform type.
2161 if (valueType == uniformType)
2162 {
2163 return true;
2164 }
2165
2166 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2167 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002168}
2169
Jamie Madill5b772312018-03-08 20:28:32 -05002170bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002171{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002172 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002173 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002174 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2175 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002176}
2177
Jamie Madill5b772312018-03-08 20:28:32 -05002178bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002179{
2180 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002181 Program *programObject = context->getGLState().getProgram();
Frank Henigmana98a6472017-02-02 21:38:32 -05002182 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2183 ValidateUniform1ivValue(context, uniform->type, count, value);
2184}
2185
Jamie Madill5b772312018-03-08 20:28:32 -05002186bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002187 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002188 GLint location,
2189 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002190 GLboolean transpose)
2191{
Geoff Lang92019432017-11-20 13:09:34 -05002192 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002194 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002195 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002196 }
2197
Jamie Madill62d31cb2015-09-11 13:25:51 -04002198 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002199 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002200 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2201 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002202}
2203
Jamie Madill5b772312018-03-08 20:28:32 -05002204bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002205{
2206 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002208 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002209 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002210 }
2211
Jamie Madill0af26e12015-03-05 19:54:33 -05002212 const Caps &caps = context->getCaps();
2213
Jamie Madill893ab082014-05-16 16:56:10 -04002214 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2215 {
2216 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2217
Jamie Madill0af26e12015-03-05 19:54:33 -05002218 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002220 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002221 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002222 }
2223 }
2224
2225 switch (pname)
2226 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002227 case GL_TEXTURE_BINDING_2D:
2228 case GL_TEXTURE_BINDING_CUBE_MAP:
2229 case GL_TEXTURE_BINDING_3D:
2230 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002231 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002232 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002233 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2234 if (!context->getExtensions().textureRectangle)
2235 {
2236 context->handleError(InvalidEnum()
2237 << "ANGLE_texture_rectangle extension not present");
2238 return false;
2239 }
2240 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002241 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2242 if (!context->getExtensions().eglStreamConsumerExternal &&
2243 !context->getExtensions().eglImageExternal)
2244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002245 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2246 "nor GL_OES_EGL_image_external "
2247 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002248 return false;
2249 }
2250 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002251
He Yunchaoced53ae2016-11-29 15:00:51 +08002252 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2253 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002254 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002255 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2256 ASSERT(readFramebuffer);
2257
Jamie Madill427064d2018-04-13 16:20:34 -04002258 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002259 {
Geoff Langb1196682014-07-23 13:47:29 -04002260 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002261 }
2262
Jamie Madille98b1b52018-03-08 09:47:23 -05002263 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002264 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002266 return false;
2267 }
2268
Jamie Madille98b1b52018-03-08 09:47:23 -05002269 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002270 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002272 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002273 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002274 }
2275 }
2276 break;
2277
He Yunchaoced53ae2016-11-29 15:00:51 +08002278 default:
2279 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002280 }
2281
2282 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002283 if (*numParams == 0)
2284 {
2285 return false;
2286 }
2287
2288 return true;
2289}
2290
Brandon Jonesd1049182018-03-28 10:02:20 -07002291bool ValidateGetBooleanvRobustANGLE(Context *context,
2292 GLenum pname,
2293 GLsizei bufSize,
2294 GLsizei *length,
2295 GLboolean *params)
2296{
2297 GLenum nativeType;
2298 unsigned int numParams = 0;
2299
2300 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2301 {
2302 return false;
2303 }
2304
2305 SetRobustLengthParam(length, numParams);
2306
2307 return true;
2308}
2309
2310bool ValidateGetFloatvRobustANGLE(Context *context,
2311 GLenum pname,
2312 GLsizei bufSize,
2313 GLsizei *length,
2314 GLfloat *params)
2315{
2316 GLenum nativeType;
2317 unsigned int numParams = 0;
2318
2319 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2320 {
2321 return false;
2322 }
2323
2324 SetRobustLengthParam(length, numParams);
2325
2326 return true;
2327}
2328
2329bool ValidateGetIntegervRobustANGLE(Context *context,
2330 GLenum pname,
2331 GLsizei bufSize,
2332 GLsizei *length,
2333 GLint *data)
2334{
2335 GLenum nativeType;
2336 unsigned int numParams = 0;
2337
2338 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2339 {
2340 return false;
2341 }
2342
2343 SetRobustLengthParam(length, numParams);
2344
2345 return true;
2346}
2347
2348bool ValidateGetInteger64vRobustANGLE(Context *context,
2349 GLenum pname,
2350 GLsizei bufSize,
2351 GLsizei *length,
2352 GLint64 *data)
2353{
2354 GLenum nativeType;
2355 unsigned int numParams = 0;
2356
2357 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2358 {
2359 return false;
2360 }
2361
2362 if (nativeType == GL_INT_64_ANGLEX)
2363 {
2364 CastStateValues(context, nativeType, pname, numParams, data);
2365 return false;
2366 }
2367
2368 SetRobustLengthParam(length, numParams);
2369 return true;
2370}
2371
Jamie Madill5b772312018-03-08 20:28:32 -05002372bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002373 GLenum pname,
2374 GLsizei bufSize,
2375 GLenum *nativeType,
2376 unsigned int *numParams)
2377{
2378 if (!ValidateRobustEntryPoint(context, bufSize))
2379 {
2380 return false;
2381 }
2382
2383 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2384 {
2385 return false;
2386 }
2387
2388 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002389 {
2390 return false;
2391 }
2392
2393 return true;
2394}
2395
Jamie Madill5b772312018-03-08 20:28:32 -05002396bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002397 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002398 GLint level,
2399 GLenum internalformat,
2400 bool isSubImage,
2401 GLint xoffset,
2402 GLint yoffset,
2403 GLint zoffset,
2404 GLint x,
2405 GLint y,
2406 GLsizei width,
2407 GLsizei height,
2408 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002409 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002410{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002411 TextureType texType = TextureTargetToType(target);
2412
Brandon Jones6cad5662017-06-14 13:25:13 -07002413 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002414 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002415 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2416 return false;
2417 }
2418
2419 if (width < 0 || height < 0)
2420 {
2421 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002422 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002423 }
2424
He Yunchaoced53ae2016-11-29 15:00:51 +08002425 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2426 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002428 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002429 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002430 }
2431
2432 if (border != 0)
2433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002434 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002435 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002436 }
2437
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002438 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002440 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002442 }
2443
Jamie Madill43da7c42018-08-01 11:34:49 -04002444 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002445 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002446 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002447 {
Geoff Langb1196682014-07-23 13:47:29 -04002448 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002449 }
2450
Jamie Madille98b1b52018-03-08 09:47:23 -05002451 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002452 {
Geoff Langb1196682014-07-23 13:47:29 -04002453 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002454 }
2455
Martin Radev138064f2016-07-15 12:03:41 +03002456 if (readFramebuffer->getReadBufferState() == GL_NONE)
2457 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002458 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002459 return false;
2460 }
2461
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002462 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2463 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002464 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002465 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002466 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2467 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002468 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002469 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002470 return false;
2471 }
2472
Martin Radev04e2c3b2017-07-27 16:54:35 +03002473 // ANGLE_multiview spec, Revision 1:
2474 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2475 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002476 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2477 // framebuffer is more than one.
2478 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002479 {
2480 context->handleError(InvalidFramebufferOperation()
2481 << "The active read framebuffer object has multiview attachments.");
2482 return false;
2483 }
2484
Jamie Madill43da7c42018-08-01 11:34:49 -04002485 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002486
Geoff Langaae65a42014-05-26 12:43:44 -04002487 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002488 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002489 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002490 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002491 maxDimension = caps.max2DTextureSize;
2492 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002493
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002494 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002495 maxDimension = caps.maxCubeMapTextureSize;
2496 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002497
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002498 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002499 maxDimension = caps.maxRectangleTextureSize;
2500 break;
2501
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002502 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002503 maxDimension = caps.max2DTextureSize;
2504 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002505
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002506 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002507 maxDimension = caps.max3DTextureSize;
2508 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002509
He Yunchaoced53ae2016-11-29 15:00:51 +08002510 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002511 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002512 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 }
2514
Jamie Madill43da7c42018-08-01 11:34:49 -04002515 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002516 if (!texture)
2517 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002518 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002519 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002520 }
2521
Geoff Lang69cce582015-09-17 13:20:36 -04002522 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002524 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002525 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002526 }
2527
Jamie Madill43da7c42018-08-01 11:34:49 -04002528 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002529 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002530 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002531
Geoff Lang966c9402017-04-18 12:38:27 -04002532 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002534 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002535 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002536 }
2537
2538 if (isSubImage)
2539 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002540 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2541 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2542 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002544 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002545 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002546 }
2547 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002548 else
2549 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002550 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002551 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002552 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002553 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002554 }
2555
Geoff Langeb66a6e2016-10-31 13:06:12 -04002556 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002557 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002558 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002559 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002560 }
2561
2562 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002563 if (static_cast<int>(width) > maxLevelDimension ||
2564 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002565 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002566 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002567 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002568 }
2569 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002570
Jamie Madill0c8abca2016-07-22 20:21:26 -04002571 if (textureFormatOut)
2572 {
2573 *textureFormatOut = texture->getFormat(target, level);
2574 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002575
2576 // Detect texture copying feedback loops for WebGL.
2577 if (context->getExtensions().webglCompatibility)
2578 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002579 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002580 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002582 return false;
2583 }
2584 }
2585
Jamie Madill560a8d82014-05-21 13:06:20 -04002586 return true;
2587}
2588
Jamie Madill493f9572018-05-24 19:52:15 -04002589bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002590{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002591 const Extensions &extensions = context->getExtensions();
2592
Jamie Madill1aeb1312014-06-20 13:21:25 -04002593 switch (mode)
2594 {
Jamie Madill493f9572018-05-24 19:52:15 -04002595 case PrimitiveMode::Points:
2596 case PrimitiveMode::Lines:
2597 case PrimitiveMode::LineLoop:
2598 case PrimitiveMode::LineStrip:
2599 case PrimitiveMode::Triangles:
2600 case PrimitiveMode::TriangleStrip:
2601 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002602 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002603
Jamie Madill493f9572018-05-24 19:52:15 -04002604 case PrimitiveMode::LinesAdjacency:
2605 case PrimitiveMode::LineStripAdjacency:
2606 case PrimitiveMode::TrianglesAdjacency:
2607 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002608 if (!extensions.geometryShader)
2609 {
2610 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2611 return false;
2612 }
2613 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002614 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002615 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002616 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002617 }
2618
Jamie Madill250d33f2014-06-06 17:09:03 -04002619 if (count < 0)
2620 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002621 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002622 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002623 }
2624
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002625 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002626
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002627 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2628 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2629 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madillcc73f242018-08-01 11:34:48 -04002630 if (!extensions.webglCompatibility && state.getVertexArray()->hasMappedEnabledArrayBuffer())
Jamie Madill250d33f2014-06-06 17:09:03 -04002631 {
Jamie Madillcc73f242018-08-01 11:34:48 -04002632 context->handleError(InvalidOperation());
2633 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002634 }
2635
Jamie Madillcbcde722017-01-06 14:50:00 -05002636 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2637 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002638 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002639 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002640 {
Ken Russellb9f92502018-01-27 19:00:26 -08002641 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002642 const FramebufferAttachment *dsAttachment =
2643 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002644 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2645 ASSERT(stencilBits <= 8);
2646
Jinyoung Hur85769f02015-10-20 17:08:44 -04002647 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002648 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002649 {
Ken Russellb9f92502018-01-27 19:00:26 -08002650 GLuint maxStencilValue = (1 << stencilBits) - 1;
2651
2652 bool differentRefs =
2653 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2654 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2655 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2656 (depthStencilState.stencilBackWritemask & maxStencilValue);
2657 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2658 (depthStencilState.stencilBackMask & maxStencilValue);
2659
2660 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002661 {
Ken Russellb9f92502018-01-27 19:00:26 -08002662 if (!extensions.webglCompatibility)
2663 {
Jamie Madilla2f043d2018-07-10 17:21:20 -04002664 WARN() << "This ANGLE implementation does not support separate front/back "
2665 "stencil writemasks, reference values, or stencil mask values.";
Ken Russellb9f92502018-01-27 19:00:26 -08002666 }
2667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2668 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002669 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002670 }
Jamie Madillac528012014-06-20 13:21:23 -04002671 }
2672
Jamie Madill427064d2018-04-13 16:20:34 -04002673 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002674 {
Geoff Langb1196682014-07-23 13:47:29 -04002675 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002676 }
2677
Jamie Madill2da53562018-08-01 11:34:47 -04002678 if (context->getStateCache().hasAnyEnabledClientAttrib())
2679 {
2680 if (!ValidateDrawClientAttribs(context))
2681 {
2682 return false;
2683 }
2684 }
2685
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002686 // If we are running GLES1, there is no current program.
2687 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002688 {
Jamie Madill43da7c42018-08-01 11:34:49 -04002689 Program *program = state.getProgram();
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002690 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002691 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002693 return false;
2694 }
Martin Radev7e69f762017-07-27 14:54:13 +03002695
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002696 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2697 // vertex shader stage or fragment shader stage is a undefined behaviour.
2698 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2699 // produce undefined result.
2700 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2701 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002702 {
2703 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002704 << "It is a undefined behaviour to render without "
2705 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002706 return false;
2707 }
Martin Radevffe754b2017-07-31 10:38:07 +03002708
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002709 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002710 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002711 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002712 return false;
2713 }
2714
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002715 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002716 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002717 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2718 const int framebufferNumViews = framebuffer->getNumViews();
2719 if (framebufferNumViews != programNumViews)
2720 {
2721 context->handleError(InvalidOperation()
2722 << "The number of views in the active program "
2723 "and draw framebuffer does not match.");
2724 return false;
2725 }
2726
2727 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2728 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2729 framebufferNumViews > 1)
2730 {
2731 context->handleError(InvalidOperation()
2732 << "There is an active transform feedback object "
2733 "when the number of views in the active draw "
2734 "framebuffer is greater than 1.");
2735 return false;
2736 }
2737
2738 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2739 state.isQueryActive(QueryType::TimeElapsed))
2740 {
2741 context->handleError(InvalidOperation()
2742 << "There is an active query for target "
2743 "GL_TIME_ELAPSED_EXT when the number of "
2744 "views in the active draw framebuffer is "
2745 "greater than 1.");
2746 return false;
2747 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002748 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002749
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002750 // Do geometry shader specific validations
2751 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002752 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002753 if (!IsCompatibleDrawModeWithGeometryShader(
2754 mode, program->getGeometryShaderInputPrimitiveType()))
2755 {
2756 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2757 IncompatibleDrawModeAgainstGeometryShader);
2758 return false;
2759 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002760 }
Geoff Lange0cff192017-05-30 13:04:56 -04002761
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002762 // Uniform buffer validation
2763 for (unsigned int uniformBlockIndex = 0;
2764 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002765 {
Jamie Madill43da7c42018-08-01 11:34:49 -04002766 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002767 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2768 const OffsetBindingPointer<Buffer> &uniformBuffer =
2769 state.getIndexedUniformBuffer(blockBinding);
2770
2771 if (uniformBuffer.get() == nullptr)
2772 {
2773 // undefined behaviour
2774 context->handleError(
2775 InvalidOperation()
2776 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2777 return false;
2778 }
2779
2780 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2781 if (uniformBufferSize < uniformBlock.dataSize)
2782 {
2783 // undefined behaviour
2784 context->handleError(
2785 InvalidOperation()
2786 << "It is undefined behaviour to use a uniform buffer that is too small.");
2787 return false;
2788 }
2789
2790 if (extensions.webglCompatibility &&
2791 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2792 {
2793 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2794 UniformBufferBoundForTransformFeedback);
2795 return false;
2796 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002797 }
2798
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002799 // Do some additonal WebGL-specific validation
2800 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002801 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002802 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2803 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2804 transformFeedbackObject->buffersBoundForOtherUse())
2805 {
2806 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2807 TransformFeedbackBufferDoubleBound);
2808 return false;
2809 }
2810 // Detect rendering feedback loops for WebGL.
2811 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2812 {
2813 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2814 return false;
2815 }
2816
2817 // Detect that the vertex shader input types match the attribute types
2818 if (!ValidateVertexShaderAttributeTypeMatch(context))
2819 {
2820 return false;
2821 }
2822
2823 // Detect that the color buffer types match the fragment shader output types
2824 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2825 {
2826 return false;
2827 }
Jamie Madillac43aaa2018-07-31 11:22:13 -04002828
2829 if (count > 0)
2830 {
2831 const VertexArray *vao = context->getGLState().getVertexArray();
2832 if (vao->hasTransformFeedbackBindingConflict(context))
2833 {
2834 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2835 VertexBufferBoundForTransformFeedback);
2836 return false;
2837 }
2838 }
Geoff Lange0cff192017-05-30 13:04:56 -04002839 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002840 }
2841
Jamie Madill9fdaa492018-02-16 10:52:11 -05002842 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002843}
2844
Jamie Madill5b772312018-03-08 20:28:32 -05002845bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002846 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002847 GLint first,
2848 GLsizei count,
2849 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002850{
Jamie Madillfd716582014-06-06 17:09:04 -04002851 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002853 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002854 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002855 }
2856
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002857 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04002858 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002859 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002860 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002861 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002862 if (!ValidateTransformFeedbackPrimitiveMode(context,
2863 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002864 {
James Darpinian30b604d2018-03-12 17:26:57 -07002865 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2866 return false;
2867 }
2868
2869 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2870 {
2871 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2872 return false;
2873 }
Jamie Madillfd716582014-06-06 17:09:04 -04002874 }
2875
Jiajia Qind9671222016-11-29 16:30:31 +08002876 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002877 {
2878 return false;
2879 }
2880
Corentin Wallez71168a02016-12-19 15:11:18 -08002881 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002882 // - first < 0 has been checked as an error condition.
2883 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002884 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002885 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002886 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002887 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002888 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2889 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2890 {
2891 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2892 return false;
2893 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002894
Jamie Madill2da53562018-08-01 11:34:47 -04002895 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002896 {
2897 return false;
2898 }
Jamie Madillfd716582014-06-06 17:09:04 -04002899 }
2900
2901 return true;
2902}
2903
He Yunchaoced53ae2016-11-29 15:00:51 +08002904bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002905 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002906 GLint first,
2907 GLsizei count,
2908 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002909{
Geoff Lang63c5a592017-09-27 14:08:16 -04002910 if (!context->getExtensions().instancedArrays)
2911 {
2912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2913 return false;
2914 }
2915
Corentin Wallez170efbf2017-05-02 13:45:01 -04002916 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002917 {
2918 return false;
2919 }
2920
Corentin Wallez0dc97812017-06-22 14:38:44 -04002921 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002922}
2923
Jamie Madill493f9572018-05-24 19:52:15 -04002924bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002925{
Jamie Madill250d33f2014-06-06 17:09:03 -04002926 switch (type)
2927 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002928 case GL_UNSIGNED_BYTE:
2929 case GL_UNSIGNED_SHORT:
2930 break;
2931 case GL_UNSIGNED_INT:
2932 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2933 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002934 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002935 return false;
2936 }
2937 break;
2938 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002939 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002940 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002941 }
2942
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002943 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002944
Jamie Madill43da7c42018-08-01 11:34:49 -04002945 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002946 if (curTransformFeedback && curTransformFeedback->isActive() &&
2947 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002948 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002949 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2950 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2951 if (context->getExtensions().geometryShader)
2952 {
2953 if (!ValidateTransformFeedbackPrimitiveMode(
2954 context, curTransformFeedback->getPrimitiveMode(), mode))
2955 {
2956 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2957 return false;
2958 }
2959 }
2960 else
2961 {
2962 // It is an invalid operation to call DrawElements, DrawRangeElements or
2963 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2964 // 86)
2965 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2966 UnsupportedDrawModeForTransformFeedback);
2967 return false;
2968 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002969 }
2970
Jiajia Qind9671222016-11-29 16:30:31 +08002971 return true;
2972}
2973
Jamie Madill5b772312018-03-08 20:28:32 -05002974bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002975 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002976 GLsizei count,
2977 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002978 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002979 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002980{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002981 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08002982 return false;
2983
2984 const State &state = context->getGLState();
2985
Corentin Wallez170efbf2017-05-02 13:45:01 -04002986 if (!ValidateDrawBase(context, mode, count))
2987 {
2988 return false;
2989 }
2990
Jamie Madill43da7c42018-08-01 11:34:49 -04002991 const VertexArray *vao = state.getVertexArray();
2992 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002993
Jamie Madill43da7c42018-08-01 11:34:49 -04002994 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002995
2996 if (context->getExtensions().webglCompatibility)
2997 {
2998 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2999 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3000 {
3001 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3002 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3003 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003004 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003005 return false;
3006 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003007
3008 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3009 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3010 // error is generated.
3011 if (reinterpret_cast<intptr_t>(indices) < 0)
3012 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003013 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003014 return false;
3015 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003016 }
Jamie Madillcc73f242018-08-01 11:34:48 -04003017 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
3018 {
3019 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3020 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3021 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3022 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3023 return false;
3024 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003025
3026 if (context->getExtensions().webglCompatibility ||
3027 !context->getGLState().areClientArraysEnabled())
3028 {
Brandon Jones2a018152018-06-08 15:59:26 -07003029 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003030 {
3031 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003032 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3033 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003035 return false;
3036 }
3037 }
3038
Jamie Madill9fdaa492018-02-16 10:52:11 -05003039 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003040 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003041 // This is an application error that would normally result in a crash, but we catch it and
3042 // return an error
3043 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3044 return false;
3045 }
3046
3047 if (count > 0 && elementArrayBuffer)
3048 {
3049 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3050 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3051 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3052 constexpr uint64_t kMaxTypeSize = 8;
3053 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3054 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3055 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3056
3057 uint64_t typeSize = typeBytes;
3058 uint64_t elementCount = static_cast<uint64_t>(count);
3059 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3060
3061 // Doing the multiplication here is overflow-safe
3062 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3063
3064 // The offset can be any value, check for overflows
3065 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3066 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003067 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003068 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3069 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003070 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003071
3072 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3073 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003074 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003075 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3076 return false;
3077 }
3078
3079 ASSERT(isPow2(typeSize) && typeSize > 0);
3080 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3081 {
3082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003083 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003084 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003085
3086 if (context->getExtensions().webglCompatibility &&
3087 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3088 {
3089 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3090 ElementArrayBufferBoundForTransformFeedback);
3091 return false;
3092 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003093 }
3094
Jamie Madill2da53562018-08-01 11:34:47 -04003095 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003096 {
3097 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003098 const DrawCallParams &params = context->getParams<DrawCallParams>();
3099 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3100 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003101
3102 // If we use an index greater than our maximum supported index range, return an error.
3103 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3104 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003105 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003106 {
3107 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3108 return false;
3109 }
3110
Jamie Madill2da53562018-08-01 11:34:47 -04003111 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003112 {
3113 return false;
3114 }
3115
3116 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003117 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003118 }
3119
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003120 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003121}
3122
Jamie Madill5b772312018-03-08 20:28:32 -05003123bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003124 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003125 GLsizei count,
3126 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003127 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003128 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003129{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003130 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003131}
3132
Geoff Lang3edfe032015-09-04 16:38:24 -04003133bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003134 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003135 GLsizei count,
3136 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003137 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003138 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003139{
Geoff Lang63c5a592017-09-27 14:08:16 -04003140 if (!context->getExtensions().instancedArrays)
3141 {
3142 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3143 return false;
3144 }
3145
Corentin Wallez170efbf2017-05-02 13:45:01 -04003146 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003147 {
3148 return false;
3149 }
3150
Corentin Wallez0dc97812017-06-22 14:38:44 -04003151 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003152}
3153
He Yunchaoced53ae2016-11-29 15:00:51 +08003154bool ValidateFramebufferTextureBase(Context *context,
3155 GLenum target,
3156 GLenum attachment,
3157 GLuint texture,
3158 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003159{
Geoff Lange8afa902017-09-27 15:00:43 -04003160 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003161 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003162 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003163 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003164 }
3165
3166 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003167 {
3168 return false;
3169 }
3170
Jamie Madill55ec3b12014-07-03 10:38:57 -04003171 if (texture != 0)
3172 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003173 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003174
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003175 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003177 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003179 }
3180
3181 if (level < 0)
3182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003183 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003184 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003185 }
3186 }
3187
Jamie Madill43da7c42018-08-01 11:34:49 -04003188 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003189 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003190
Jamie Madill84115c92015-04-23 15:00:07 -04003191 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003194 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003195 }
3196
3197 return true;
3198}
3199
Geoff Langb1196682014-07-23 13:47:29 -04003200bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003201{
3202 if (program == 0)
3203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003204 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003205 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003206 }
3207
Jamie Madill43da7c42018-08-01 11:34:49 -04003208 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003209 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003210 {
3211 return false;
3212 }
3213
Jamie Madill0063c512014-08-25 15:47:53 -04003214 if (!programObject || !programObject->isLinked())
3215 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003216 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003217 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003218 }
3219
Geoff Lang7dd2e102014-11-10 15:19:26 -05003220 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003222 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003223 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003224 }
3225
Jamie Madill0063c512014-08-25 15:47:53 -04003226 return true;
3227}
3228
Geoff Langf41d0ee2016-10-07 13:04:23 -04003229static bool ValidateSizedGetUniform(Context *context,
3230 GLuint program,
3231 GLint location,
3232 GLsizei bufSize,
3233 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003234{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003235 if (length)
3236 {
3237 *length = 0;
3238 }
3239
Jamie Madill78f41802014-08-25 15:47:55 -04003240 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003241 {
Jamie Madill78f41802014-08-25 15:47:55 -04003242 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003243 }
3244
Geoff Langf41d0ee2016-10-07 13:04:23 -04003245 if (bufSize < 0)
3246 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003247 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003248 return false;
3249 }
3250
Jamie Madill43da7c42018-08-01 11:34:49 -04003251 Program *programObject = context->getProgram(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003252 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003253
Jamie Madill78f41802014-08-25 15:47:55 -04003254 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003255 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003256 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003257 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003258 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003259 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003260 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003261 }
3262
Geoff Langf41d0ee2016-10-07 13:04:23 -04003263 if (length)
3264 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003265 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003266 }
3267
Jamie Madill0063c512014-08-25 15:47:53 -04003268 return true;
3269}
3270
He Yunchaoced53ae2016-11-29 15:00:51 +08003271bool ValidateGetnUniformfvEXT(Context *context,
3272 GLuint program,
3273 GLint location,
3274 GLsizei bufSize,
3275 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003276{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003277 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003278}
3279
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003280bool ValidateGetnUniformfvRobustANGLE(Context *context,
3281 GLuint program,
3282 GLint location,
3283 GLsizei bufSize,
3284 GLsizei *length,
3285 GLfloat *params)
3286{
3287 UNIMPLEMENTED();
3288 return false;
3289}
3290
He Yunchaoced53ae2016-11-29 15:00:51 +08003291bool ValidateGetnUniformivEXT(Context *context,
3292 GLuint program,
3293 GLint location,
3294 GLsizei bufSize,
3295 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003296{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003297 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3298}
3299
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003300bool ValidateGetnUniformivRobustANGLE(Context *context,
3301 GLuint program,
3302 GLint location,
3303 GLsizei bufSize,
3304 GLsizei *length,
3305 GLint *params)
3306{
3307 UNIMPLEMENTED();
3308 return false;
3309}
3310
3311bool ValidateGetnUniformuivRobustANGLE(Context *context,
3312 GLuint program,
3313 GLint location,
3314 GLsizei bufSize,
3315 GLsizei *length,
3316 GLuint *params)
3317{
3318 UNIMPLEMENTED();
3319 return false;
3320}
3321
Geoff Langf41d0ee2016-10-07 13:04:23 -04003322bool ValidateGetUniformfvRobustANGLE(Context *context,
3323 GLuint program,
3324 GLint location,
3325 GLsizei bufSize,
3326 GLsizei *length,
3327 GLfloat *params)
3328{
3329 if (!ValidateRobustEntryPoint(context, bufSize))
3330 {
3331 return false;
3332 }
3333
Brandon Jonesd1049182018-03-28 10:02:20 -07003334 GLsizei writeLength = 0;
3335
Geoff Langf41d0ee2016-10-07 13:04:23 -04003336 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003337 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3338 {
3339 return false;
3340 }
3341
3342 SetRobustLengthParam(length, writeLength);
3343
3344 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003345}
3346
3347bool ValidateGetUniformivRobustANGLE(Context *context,
3348 GLuint program,
3349 GLint location,
3350 GLsizei bufSize,
3351 GLsizei *length,
3352 GLint *params)
3353{
3354 if (!ValidateRobustEntryPoint(context, bufSize))
3355 {
3356 return false;
3357 }
3358
Brandon Jonesd1049182018-03-28 10:02:20 -07003359 GLsizei writeLength = 0;
3360
Geoff Langf41d0ee2016-10-07 13:04:23 -04003361 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003362 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3363 {
3364 return false;
3365 }
3366
3367 SetRobustLengthParam(length, writeLength);
3368
3369 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003370}
3371
3372bool ValidateGetUniformuivRobustANGLE(Context *context,
3373 GLuint program,
3374 GLint location,
3375 GLsizei bufSize,
3376 GLsizei *length,
3377 GLuint *params)
3378{
3379 if (!ValidateRobustEntryPoint(context, bufSize))
3380 {
3381 return false;
3382 }
3383
3384 if (context->getClientMajorVersion() < 3)
3385 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003386 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003387 return false;
3388 }
3389
Brandon Jonesd1049182018-03-28 10:02:20 -07003390 GLsizei writeLength = 0;
3391
Geoff Langf41d0ee2016-10-07 13:04:23 -04003392 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003393 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3394 {
3395 return false;
3396 }
3397
3398 SetRobustLengthParam(length, writeLength);
3399
3400 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003401}
3402
He Yunchaoced53ae2016-11-29 15:00:51 +08003403bool ValidateDiscardFramebufferBase(Context *context,
3404 GLenum target,
3405 GLsizei numAttachments,
3406 const GLenum *attachments,
3407 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003408{
3409 if (numAttachments < 0)
3410 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003411 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003412 return false;
3413 }
3414
3415 for (GLsizei i = 0; i < numAttachments; ++i)
3416 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003417 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003418 {
3419 if (defaultFramebuffer)
3420 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003422 return false;
3423 }
3424
3425 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003427 context->handleError(InvalidOperation() << "Requested color attachment is "
3428 "greater than the maximum supported "
3429 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003430 return false;
3431 }
3432 }
3433 else
3434 {
3435 switch (attachments[i])
3436 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003437 case GL_DEPTH_ATTACHMENT:
3438 case GL_STENCIL_ATTACHMENT:
3439 case GL_DEPTH_STENCIL_ATTACHMENT:
3440 if (defaultFramebuffer)
3441 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003442 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3443 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003444 return false;
3445 }
3446 break;
3447 case GL_COLOR:
3448 case GL_DEPTH:
3449 case GL_STENCIL:
3450 if (!defaultFramebuffer)
3451 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003452 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3453 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003454 return false;
3455 }
3456 break;
3457 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003458 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003459 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003460 }
3461 }
3462 }
3463
3464 return true;
3465}
3466
Austin Kinross6ee1e782015-05-29 17:05:37 -07003467bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3468{
Jamie Madill007530e2017-12-28 14:27:04 -05003469 if (!context->getExtensions().debugMarker)
3470 {
3471 // The debug marker calls should not set error state
3472 // However, it seems reasonable to set an error state if the extension is not enabled
3473 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3474 return false;
3475 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003476
Jamie Madill007530e2017-12-28 14:27:04 -05003477 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003478 if (length < 0)
3479 {
3480 return false;
3481 }
3482
3483 if (marker == nullptr)
3484 {
3485 return false;
3486 }
3487
3488 return true;
3489}
3490
3491bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3492{
Jamie Madill007530e2017-12-28 14:27:04 -05003493 if (!context->getExtensions().debugMarker)
3494 {
3495 // The debug marker calls should not set error state
3496 // However, it seems reasonable to set an error state if the extension is not enabled
3497 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3498 return false;
3499 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003500
Jamie Madill007530e2017-12-28 14:27:04 -05003501 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003502 if (length < 0)
3503 {
3504 return false;
3505 }
3506
3507 if (length > 0 && marker == nullptr)
3508 {
3509 return false;
3510 }
3511
3512 return true;
3513}
3514
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003515bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003516{
Geoff Langa8406172015-07-21 16:53:39 -04003517 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003519 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003520 return false;
3521 }
3522
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003523 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003524 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003525 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003526 if (!context->getExtensions().eglImage)
3527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003528 context->handleError(InvalidEnum()
3529 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003530 }
3531 break;
3532
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003533 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003534 if (!context->getExtensions().eglImageExternal)
3535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003536 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3537 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003538 }
Geoff Langa8406172015-07-21 16:53:39 -04003539 break;
3540
3541 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003542 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003543 return false;
3544 }
3545
Rafael Cintron05a449a2018-06-20 18:08:04 -07003546 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003547
Jamie Madill61e16b42017-06-19 11:13:23 -04003548 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003549 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003551 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003552 return false;
3553 }
3554
Jamie Madill007530e2017-12-28 14:27:04 -05003555 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003557 context->handleError(InvalidOperation()
3558 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003559 return false;
3560 }
3561
Geoff Langca271392017-04-05 12:30:00 -04003562 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003563 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003564 if (!textureCaps.texturable)
3565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003566 context->handleError(InvalidOperation()
3567 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003568 return false;
3569 }
3570
Geoff Langdcab33b2015-07-21 13:03:16 -04003571 return true;
3572}
3573
3574bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003575 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003576 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003577{
Geoff Langa8406172015-07-21 16:53:39 -04003578 if (!context->getExtensions().eglImage)
3579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003580 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003581 return false;
3582 }
3583
3584 switch (target)
3585 {
3586 case GL_RENDERBUFFER:
3587 break;
3588
3589 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003590 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003591 return false;
3592 }
3593
Rafael Cintron05a449a2018-06-20 18:08:04 -07003594 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003595
Jamie Madill61e16b42017-06-19 11:13:23 -04003596 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003597 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003599 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003600 return false;
3601 }
3602
Geoff Langca271392017-04-05 12:30:00 -04003603 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003604 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003605 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003607 context->handleError(InvalidOperation()
3608 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003609 return false;
3610 }
3611
Geoff Langdcab33b2015-07-21 13:03:16 -04003612 return true;
3613}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003614
3615bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3616{
Geoff Lang36167ab2015-12-07 10:27:14 -05003617 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003618 {
3619 // The default VAO should always exist
3620 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003621 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003622 return false;
3623 }
3624
3625 return true;
3626}
3627
Geoff Langc5629752015-12-07 16:29:04 -05003628bool ValidateProgramBinaryBase(Context *context,
3629 GLuint program,
3630 GLenum binaryFormat,
3631 const void *binary,
3632 GLint length)
3633{
3634 Program *programObject = GetValidProgram(context, program);
3635 if (programObject == nullptr)
3636 {
3637 return false;
3638 }
3639
3640 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3641 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3642 programBinaryFormats.end())
3643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003644 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003645 return false;
3646 }
3647
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003648 if (context->hasActiveTransformFeedback(program))
3649 {
3650 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003651 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3652 "is associated with an active transform "
3653 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003654 return false;
3655 }
3656
Geoff Langc5629752015-12-07 16:29:04 -05003657 return true;
3658}
3659
3660bool ValidateGetProgramBinaryBase(Context *context,
3661 GLuint program,
3662 GLsizei bufSize,
3663 GLsizei *length,
3664 GLenum *binaryFormat,
3665 void *binary)
3666{
3667 Program *programObject = GetValidProgram(context, program);
3668 if (programObject == nullptr)
3669 {
3670 return false;
3671 }
3672
3673 if (!programObject->isLinked())
3674 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003675 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003676 return false;
3677 }
3678
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003679 if (context->getCaps().programBinaryFormats.empty())
3680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003681 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003682 return false;
3683 }
3684
Geoff Langc5629752015-12-07 16:29:04 -05003685 return true;
3686}
Jamie Madillc29968b2016-01-20 11:17:23 -05003687
Jamie Madill5b772312018-03-08 20:28:32 -05003688bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003689{
3690 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003691 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003692 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003693 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3694 return false;
3695 }
3696 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3697 {
3698 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003699 return false;
3700 }
3701
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003702 ASSERT(context->getGLState().getDrawFramebuffer());
3703 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003704 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3705
3706 // This should come first before the check for the default frame buffer
3707 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3708 // rather than INVALID_OPERATION
3709 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3710 {
3711 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3712
3713 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003714 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3715 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003716 {
3717 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003718 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3719 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3720 // 3.1 is still a bit ambiguous about the error, but future specs are
3721 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003722 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003723 return false;
3724 }
3725 else if (bufs[colorAttachment] >= maxColorAttachment)
3726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003727 context->handleError(InvalidOperation()
3728 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003729 return false;
3730 }
3731 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3732 frameBufferId != 0)
3733 {
3734 // INVALID_OPERATION-GL is bound to buffer and ith argument
3735 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003736 context->handleError(InvalidOperation()
3737 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003738 return false;
3739 }
3740 }
3741
3742 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3743 // and n is not 1 or bufs is bound to value other than BACK and NONE
3744 if (frameBufferId == 0)
3745 {
3746 if (n != 1)
3747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003748 context->handleError(InvalidOperation()
3749 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003750 return false;
3751 }
3752
3753 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003755 context->handleError(
3756 InvalidOperation()
3757 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003758 return false;
3759 }
3760 }
3761
3762 return true;
3763}
3764
Geoff Lang496c02d2016-10-20 11:38:11 -07003765bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003766 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003767 GLenum pname,
3768 GLsizei *length,
3769 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003770{
Geoff Lang496c02d2016-10-20 11:38:11 -07003771 if (length)
3772 {
3773 *length = 0;
3774 }
3775
3776 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3777 {
3778 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003779 InvalidOperation()
3780 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003781 return false;
3782 }
3783
Corentin Walleze4477002017-12-01 14:39:58 -05003784 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003785 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003786 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003787 return false;
3788 }
3789
Geoff Lang496c02d2016-10-20 11:38:11 -07003790 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003791 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003792 case GL_BUFFER_MAP_POINTER:
3793 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003794
Geoff Lang496c02d2016-10-20 11:38:11 -07003795 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003796 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003797 return false;
3798 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003799
3800 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3801 // target bound to zero generate an INVALID_OPERATION error."
3802 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003803 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003805 context->handleError(InvalidOperation()
3806 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003807 return false;
3808 }
3809
Geoff Lang496c02d2016-10-20 11:38:11 -07003810 if (length)
3811 {
3812 *length = 1;
3813 }
3814
Olli Etuaho4f667482016-03-30 15:56:35 +03003815 return true;
3816}
3817
Corentin Wallez336129f2017-10-17 15:55:40 -04003818bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003819{
Corentin Walleze4477002017-12-01 14:39:58 -05003820 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003821 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003822 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003823 return false;
3824 }
3825
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003826 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003827
3828 if (buffer == nullptr || !buffer->isMapped())
3829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003831 return false;
3832 }
3833
3834 return true;
3835}
3836
3837bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003838 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003839 GLintptr offset,
3840 GLsizeiptr length,
3841 GLbitfield access)
3842{
Corentin Walleze4477002017-12-01 14:39:58 -05003843 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003844 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003845 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 return false;
3847 }
3848
Brandon Jones6cad5662017-06-14 13:25:13 -07003849 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003850 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003851 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3852 return false;
3853 }
3854
3855 if (length < 0)
3856 {
3857 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 return false;
3859 }
3860
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003861 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003862
3863 if (!buffer)
3864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003865 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003866 return false;
3867 }
3868
3869 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003870 CheckedNumeric<size_t> checkedOffset(offset);
3871 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003872
Jamie Madille2e406c2016-06-02 13:04:10 -04003873 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003875 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003876 return false;
3877 }
3878
3879 // Check for invalid bits in the mask
3880 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3881 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3882 GL_MAP_UNSYNCHRONIZED_BIT;
3883
3884 if (access & ~(allAccessBits))
3885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003886 context->handleError(InvalidValue()
3887 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003888 return false;
3889 }
3890
3891 if (length == 0)
3892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003893 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003894 return false;
3895 }
3896
3897 if (buffer->isMapped())
3898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003899 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 return false;
3901 }
3902
3903 // Check for invalid bit combinations
3904 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3905 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003906 context->handleError(InvalidOperation()
3907 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 return false;
3909 }
3910
3911 GLbitfield writeOnlyBits =
3912 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3913
3914 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003916 context->handleError(InvalidOperation()
3917 << "Invalid access bits when mapping buffer for reading: 0x"
3918 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003919 return false;
3920 }
3921
3922 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003924 context->handleError(
3925 InvalidOperation()
3926 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003927 return false;
3928 }
Geoff Lang79f71042017-08-14 16:43:43 -04003929
3930 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003931}
3932
3933bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003934 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003935 GLintptr offset,
3936 GLsizeiptr length)
3937{
Brandon Jones6cad5662017-06-14 13:25:13 -07003938 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003939 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003940 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3941 return false;
3942 }
3943
3944 if (length < 0)
3945 {
3946 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003947 return false;
3948 }
3949
Corentin Walleze4477002017-12-01 14:39:58 -05003950 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003951 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003952 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003953 return false;
3954 }
3955
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003956 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003957
3958 if (buffer == nullptr)
3959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003960 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003961 return false;
3962 }
3963
3964 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003966 context->handleError(InvalidOperation()
3967 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003968 return false;
3969 }
3970
3971 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003972 CheckedNumeric<size_t> checkedOffset(offset);
3973 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003974
Jamie Madille2e406c2016-06-02 13:04:10 -04003975 if (!checkedSize.IsValid() ||
3976 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003978 context->handleError(InvalidValue()
3979 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003980 return false;
3981 }
3982
3983 return true;
3984}
3985
Olli Etuaho41997e72016-03-10 13:38:39 +02003986bool ValidateGenOrDelete(Context *context, GLint n)
3987{
3988 if (n < 0)
3989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003990 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003991 return false;
3992 }
3993 return true;
3994}
3995
Jamie Madill5b772312018-03-08 20:28:32 -05003996bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003997{
3998 if (!context->getExtensions().robustClientMemory)
3999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004000 context->handleError(InvalidOperation()
4001 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004002 return false;
4003 }
4004
4005 if (bufSize < 0)
4006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004007 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 return false;
4009 }
4010
4011 return true;
4012}
4013
Jamie Madill5b772312018-03-08 20:28:32 -05004014bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004015{
4016 if (bufSize < numParams)
4017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004018 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4019 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004020 return false;
4021 }
4022
4023 return true;
4024}
4025
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004026bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004027 GLenum target,
4028 GLenum attachment,
4029 GLenum pname,
4030 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004031{
Geoff Lange8afa902017-09-27 15:00:43 -04004032 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004034 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004035 return false;
4036 }
4037
4038 int clientVersion = context->getClientMajorVersion();
4039
4040 switch (pname)
4041 {
4042 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4043 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4044 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4045 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4046 break;
4047
Martin Radeve5285d22017-07-14 16:23:53 +03004048 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4049 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4050 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4051 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4052 if (clientVersion < 3 || !context->getExtensions().multiview)
4053 {
4054 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4055 return false;
4056 }
4057 break;
4058
Geoff Langff5b2d52016-09-07 11:32:23 -04004059 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4060 if (clientVersion < 3 && !context->getExtensions().sRGB)
4061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004062 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004063 return false;
4064 }
4065 break;
4066
4067 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4068 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4069 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4070 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4071 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4072 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4073 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4074 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4075 if (clientVersion < 3)
4076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004077 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004078 return false;
4079 }
4080 break;
4081
Jiawei Shaoa8802472018-05-28 11:17:47 +08004082 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4083 if (!context->getExtensions().geometryShader)
4084 {
4085 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4086 return false;
4087 }
4088 break;
4089
Geoff Langff5b2d52016-09-07 11:32:23 -04004090 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004091 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004092 return false;
4093 }
4094
4095 // Determine if the attachment is a valid enum
4096 switch (attachment)
4097 {
4098 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004099 case GL_DEPTH:
4100 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004101 if (clientVersion < 3)
4102 {
Geoff Langfa125c92017-10-24 13:01:46 -04004103 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004104 return false;
4105 }
4106 break;
4107
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004108 case GL_DEPTH_STENCIL_ATTACHMENT:
4109 if (clientVersion < 3 && !context->isWebGL1())
4110 {
4111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4112 return false;
4113 }
4114 break;
4115
Geoff Langfa125c92017-10-24 13:01:46 -04004116 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004117 case GL_DEPTH_ATTACHMENT:
4118 case GL_STENCIL_ATTACHMENT:
4119 break;
4120
4121 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004122 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4123 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004124 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4125 {
Geoff Langfa125c92017-10-24 13:01:46 -04004126 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004127 return false;
4128 }
4129 break;
4130 }
4131
4132 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4133 ASSERT(framebuffer);
4134
4135 if (framebuffer->id() == 0)
4136 {
4137 if (clientVersion < 3)
4138 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004139 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004140 return false;
4141 }
4142
4143 switch (attachment)
4144 {
4145 case GL_BACK:
4146 case GL_DEPTH:
4147 case GL_STENCIL:
4148 break;
4149
4150 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004151 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004152 return false;
4153 }
4154 }
4155 else
4156 {
4157 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4158 {
4159 // Valid attachment query
4160 }
4161 else
4162 {
4163 switch (attachment)
4164 {
4165 case GL_DEPTH_ATTACHMENT:
4166 case GL_STENCIL_ATTACHMENT:
4167 break;
4168
4169 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004170 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004172 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004173 return false;
4174 }
4175 break;
4176
4177 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004179 return false;
4180 }
4181 }
4182 }
4183
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004184 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004185 if (attachmentObject)
4186 {
4187 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4188 attachmentObject->type() == GL_TEXTURE ||
4189 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4190
4191 switch (pname)
4192 {
4193 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4194 if (attachmentObject->type() != GL_RENDERBUFFER &&
4195 attachmentObject->type() != GL_TEXTURE)
4196 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004197 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004198 return false;
4199 }
4200 break;
4201
4202 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4203 if (attachmentObject->type() != GL_TEXTURE)
4204 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004205 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004206 return false;
4207 }
4208 break;
4209
4210 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4211 if (attachmentObject->type() != GL_TEXTURE)
4212 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004214 return false;
4215 }
4216 break;
4217
4218 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4219 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4220 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004222 return false;
4223 }
4224 break;
4225
4226 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4227 if (attachmentObject->type() != GL_TEXTURE)
4228 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004229 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004230 return false;
4231 }
4232 break;
4233
4234 default:
4235 break;
4236 }
4237 }
4238 else
4239 {
4240 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4241 // is NONE, then querying any other pname will generate INVALID_ENUM.
4242
4243 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4244 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4245 // INVALID_OPERATION for all other pnames
4246
4247 switch (pname)
4248 {
4249 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4250 break;
4251
4252 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4253 if (clientVersion < 3)
4254 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004255 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004256 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004257 return false;
4258 }
4259 break;
4260
4261 default:
4262 if (clientVersion < 3)
4263 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004264 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004265 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004266 return false;
4267 }
4268 else
4269 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004270 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004271 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004272 return false;
4273 }
4274 }
4275 }
4276
Martin Radeve5285d22017-07-14 16:23:53 +03004277 if (numParams)
4278 {
4279 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4280 {
4281 // Only when the viewport offsets are queried we can have a varying number of output
4282 // parameters.
4283 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4284 *numParams = numViews * 2;
4285 }
4286 else
4287 {
4288 // For all other queries we can have only one output parameter.
4289 *numParams = 1;
4290 }
4291 }
4292
Geoff Langff5b2d52016-09-07 11:32:23 -04004293 return true;
4294}
4295
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004296bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004297 GLenum target,
4298 GLenum attachment,
4299 GLenum pname,
4300 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004301 GLsizei *length,
4302 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004303{
4304 if (!ValidateRobustEntryPoint(context, bufSize))
4305 {
4306 return false;
4307 }
4308
Brandon Jonesd1049182018-03-28 10:02:20 -07004309 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004310 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004311 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004312 {
4313 return false;
4314 }
4315
Brandon Jonesd1049182018-03-28 10:02:20 -07004316 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004317 {
4318 return false;
4319 }
4320
Brandon Jonesd1049182018-03-28 10:02:20 -07004321 SetRobustLengthParam(length, numParams);
4322
Geoff Langff5b2d52016-09-07 11:32:23 -04004323 return true;
4324}
4325
Jamie Madill5b772312018-03-08 20:28:32 -05004326bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004327 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004328 GLenum pname,
4329 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004330 GLsizei *length,
4331 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004332{
4333 if (!ValidateRobustEntryPoint(context, bufSize))
4334 {
4335 return false;
4336 }
4337
Brandon Jonesd1049182018-03-28 10:02:20 -07004338 GLsizei numParams = 0;
4339
4340 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004341 {
4342 return false;
4343 }
4344
Brandon Jonesd1049182018-03-28 10:02:20 -07004345 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004346 {
4347 return false;
4348 }
4349
Brandon Jonesd1049182018-03-28 10:02:20 -07004350 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004351 return true;
4352}
4353
Jamie Madill5b772312018-03-08 20:28:32 -05004354bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004355 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004356 GLenum pname,
4357 GLsizei bufSize,
4358 GLsizei *length,
4359 GLint64 *params)
4360{
Brandon Jonesd1049182018-03-28 10:02:20 -07004361 GLsizei numParams = 0;
4362
Geoff Langebebe1c2016-10-14 12:01:31 -04004363 if (!ValidateRobustEntryPoint(context, bufSize))
4364 {
4365 return false;
4366 }
4367
Brandon Jonesd1049182018-03-28 10:02:20 -07004368 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004369 {
4370 return false;
4371 }
4372
Brandon Jonesd1049182018-03-28 10:02:20 -07004373 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004374 {
4375 return false;
4376 }
4377
Brandon Jonesd1049182018-03-28 10:02:20 -07004378 SetRobustLengthParam(length, numParams);
4379
Geoff Langff5b2d52016-09-07 11:32:23 -04004380 return true;
4381}
4382
Jamie Madill5b772312018-03-08 20:28:32 -05004383bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004384{
4385 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004386 if (numParams)
4387 {
4388 *numParams = 1;
4389 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004390
4391 Program *programObject = GetValidProgram(context, program);
4392 if (!programObject)
4393 {
4394 return false;
4395 }
4396
4397 switch (pname)
4398 {
4399 case GL_DELETE_STATUS:
4400 case GL_LINK_STATUS:
4401 case GL_VALIDATE_STATUS:
4402 case GL_INFO_LOG_LENGTH:
4403 case GL_ATTACHED_SHADERS:
4404 case GL_ACTIVE_ATTRIBUTES:
4405 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4406 case GL_ACTIVE_UNIFORMS:
4407 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4408 break;
4409
4410 case GL_PROGRAM_BINARY_LENGTH:
4411 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004413 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4414 "requires GL_OES_get_program_binary or "
4415 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004416 return false;
4417 }
4418 break;
4419
4420 case GL_ACTIVE_UNIFORM_BLOCKS:
4421 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4422 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4423 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4424 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4425 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4426 if (context->getClientMajorVersion() < 3)
4427 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004429 return false;
4430 }
4431 break;
4432
Yunchao He61afff12017-03-14 15:34:03 +08004433 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004434 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004435 if (context->getClientVersion() < Version(3, 1))
4436 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004437 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004438 return false;
4439 }
4440 break;
4441
Jiawei Shao6ae51612018-02-23 14:03:25 +08004442 case GL_COMPUTE_WORK_GROUP_SIZE:
4443 if (context->getClientVersion() < Version(3, 1))
4444 {
4445 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4446 return false;
4447 }
4448
4449 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4450 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4451 // program which has not been linked successfully, or which does not contain objects to
4452 // form a compute shader.
4453 if (!programObject->isLinked())
4454 {
4455 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4456 return false;
4457 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004458 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004459 {
4460 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4461 return false;
4462 }
4463 break;
4464
Jiawei Shao447bfac2018-03-14 14:23:40 +08004465 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4466 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4467 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4468 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4469 if (!context->getExtensions().geometryShader)
4470 {
4471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4472 return false;
4473 }
4474
4475 // [EXT_geometry_shader] Chapter 7.12
4476 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4477 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4478 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4479 // successfully, or which does not contain objects to form a geometry shader.
4480 if (!programObject->isLinked())
4481 {
4482 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4483 return false;
4484 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004485 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004486 {
4487 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4488 return false;
4489 }
4490 break;
4491
Geoff Langff5b2d52016-09-07 11:32:23 -04004492 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004493 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004494 return false;
4495 }
4496
4497 return true;
4498}
4499
4500bool ValidateGetProgramivRobustANGLE(Context *context,
4501 GLuint program,
4502 GLenum pname,
4503 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004504 GLsizei *length,
4505 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004506{
4507 if (!ValidateRobustEntryPoint(context, bufSize))
4508 {
4509 return false;
4510 }
4511
Brandon Jonesd1049182018-03-28 10:02:20 -07004512 GLsizei numParams = 0;
4513
4514 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004515 {
4516 return false;
4517 }
4518
Brandon Jonesd1049182018-03-28 10:02:20 -07004519 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004520 {
4521 return false;
4522 }
4523
Brandon Jonesd1049182018-03-28 10:02:20 -07004524 SetRobustLengthParam(length, numParams);
4525
Geoff Langff5b2d52016-09-07 11:32:23 -04004526 return true;
4527}
4528
Geoff Lang740d9022016-10-07 11:20:52 -04004529bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4530 GLenum target,
4531 GLenum pname,
4532 GLsizei bufSize,
4533 GLsizei *length,
4534 GLint *params)
4535{
4536 if (!ValidateRobustEntryPoint(context, bufSize))
4537 {
4538 return false;
4539 }
4540
Brandon Jonesd1049182018-03-28 10:02:20 -07004541 GLsizei numParams = 0;
4542
4543 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004544 {
4545 return false;
4546 }
4547
Brandon Jonesd1049182018-03-28 10:02:20 -07004548 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004549 {
4550 return false;
4551 }
4552
Brandon Jonesd1049182018-03-28 10:02:20 -07004553 SetRobustLengthParam(length, numParams);
4554
Geoff Lang740d9022016-10-07 11:20:52 -04004555 return true;
4556}
4557
Geoff Langd7d0ed32016-10-07 11:33:51 -04004558bool ValidateGetShaderivRobustANGLE(Context *context,
4559 GLuint shader,
4560 GLenum pname,
4561 GLsizei bufSize,
4562 GLsizei *length,
4563 GLint *params)
4564{
4565 if (!ValidateRobustEntryPoint(context, bufSize))
4566 {
4567 return false;
4568 }
4569
Brandon Jonesd1049182018-03-28 10:02:20 -07004570 GLsizei numParams = 0;
4571
4572 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004573 {
4574 return false;
4575 }
4576
Brandon Jonesd1049182018-03-28 10:02:20 -07004577 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004578 {
4579 return false;
4580 }
4581
Brandon Jonesd1049182018-03-28 10:02:20 -07004582 SetRobustLengthParam(length, numParams);
4583
Geoff Langd7d0ed32016-10-07 11:33:51 -04004584 return true;
4585}
4586
Geoff Langc1984ed2016-10-07 12:41:00 -04004587bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004588 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004589 GLenum pname,
4590 GLsizei bufSize,
4591 GLsizei *length,
4592 GLfloat *params)
4593{
4594 if (!ValidateRobustEntryPoint(context, bufSize))
4595 {
4596 return false;
4597 }
4598
Brandon Jonesd1049182018-03-28 10:02:20 -07004599 GLsizei numParams = 0;
4600
4601 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004602 {
4603 return false;
4604 }
4605
Brandon Jonesd1049182018-03-28 10:02:20 -07004606 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004607 {
4608 return false;
4609 }
4610
Brandon Jonesd1049182018-03-28 10:02:20 -07004611 SetRobustLengthParam(length, numParams);
4612
Geoff Langc1984ed2016-10-07 12:41:00 -04004613 return true;
4614}
4615
Geoff Langc1984ed2016-10-07 12:41:00 -04004616bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004617 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004618 GLenum pname,
4619 GLsizei bufSize,
4620 GLsizei *length,
4621 GLint *params)
4622{
Brandon Jonesd1049182018-03-28 10:02:20 -07004623
Geoff Langc1984ed2016-10-07 12:41:00 -04004624 if (!ValidateRobustEntryPoint(context, bufSize))
4625 {
4626 return false;
4627 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004628 GLsizei numParams = 0;
4629 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004630 {
4631 return false;
4632 }
4633
Brandon Jonesd1049182018-03-28 10:02:20 -07004634 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004635 {
4636 return false;
4637 }
4638
Brandon Jonesd1049182018-03-28 10:02:20 -07004639 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004640 return true;
4641}
4642
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004643bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4644 TextureType target,
4645 GLenum pname,
4646 GLsizei bufSize,
4647 GLsizei *length,
4648 GLint *params)
4649{
4650 UNIMPLEMENTED();
4651 return false;
4652}
4653
4654bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4655 TextureType target,
4656 GLenum pname,
4657 GLsizei bufSize,
4658 GLsizei *length,
4659 GLuint *params)
4660{
4661 UNIMPLEMENTED();
4662 return false;
4663}
4664
Geoff Langc1984ed2016-10-07 12:41:00 -04004665bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004666 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004667 GLenum pname,
4668 GLsizei bufSize,
4669 const GLfloat *params)
4670{
4671 if (!ValidateRobustEntryPoint(context, bufSize))
4672 {
4673 return false;
4674 }
4675
4676 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4677}
4678
Geoff Langc1984ed2016-10-07 12:41:00 -04004679bool ValidateTexParameterivRobustANGLE(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 GLint *params)
4684{
4685 if (!ValidateRobustEntryPoint(context, bufSize))
4686 {
4687 return false;
4688 }
4689
4690 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4691}
4692
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004693bool ValidateTexParameterIivRobustANGLE(Context *context,
4694 TextureType target,
4695 GLenum pname,
4696 GLsizei bufSize,
4697 const GLint *params)
4698{
4699 UNIMPLEMENTED();
4700 return false;
4701}
4702
4703bool ValidateTexParameterIuivRobustANGLE(Context *context,
4704 TextureType target,
4705 GLenum pname,
4706 GLsizei bufSize,
4707 const GLuint *params)
4708{
4709 UNIMPLEMENTED();
4710 return false;
4711}
4712
Geoff Langc1984ed2016-10-07 12:41:00 -04004713bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4714 GLuint sampler,
4715 GLenum pname,
4716 GLuint bufSize,
4717 GLsizei *length,
4718 GLfloat *params)
4719{
4720 if (!ValidateRobustEntryPoint(context, bufSize))
4721 {
4722 return false;
4723 }
4724
Brandon Jonesd1049182018-03-28 10:02:20 -07004725 GLsizei numParams = 0;
4726
4727 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004728 {
4729 return false;
4730 }
4731
Brandon Jonesd1049182018-03-28 10:02:20 -07004732 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004733 {
4734 return false;
4735 }
4736
Brandon Jonesd1049182018-03-28 10:02:20 -07004737 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004738 return true;
4739}
4740
Geoff Langc1984ed2016-10-07 12:41:00 -04004741bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4742 GLuint sampler,
4743 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004744 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004745 GLsizei *length,
4746 GLint *params)
4747{
4748 if (!ValidateRobustEntryPoint(context, bufSize))
4749 {
4750 return false;
4751 }
4752
Brandon Jonesd1049182018-03-28 10:02:20 -07004753 GLsizei numParams = 0;
4754
4755 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004756 {
4757 return false;
4758 }
4759
Brandon Jonesd1049182018-03-28 10:02:20 -07004760 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004761 {
4762 return false;
4763 }
4764
Brandon Jonesd1049182018-03-28 10:02:20 -07004765 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004766 return true;
4767}
4768
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004769bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4770 GLuint sampler,
4771 GLenum pname,
4772 GLsizei bufSize,
4773 GLsizei *length,
4774 GLint *params)
4775{
4776 UNIMPLEMENTED();
4777 return false;
4778}
4779
4780bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4781 GLuint sampler,
4782 GLenum pname,
4783 GLsizei bufSize,
4784 GLsizei *length,
4785 GLuint *params)
4786{
4787 UNIMPLEMENTED();
4788 return false;
4789}
4790
Geoff Langc1984ed2016-10-07 12:41:00 -04004791bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4792 GLuint sampler,
4793 GLenum pname,
4794 GLsizei bufSize,
4795 const GLfloat *params)
4796{
4797 if (!ValidateRobustEntryPoint(context, bufSize))
4798 {
4799 return false;
4800 }
4801
4802 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4803}
4804
Geoff Langc1984ed2016-10-07 12:41:00 -04004805bool ValidateSamplerParameterivRobustANGLE(Context *context,
4806 GLuint sampler,
4807 GLenum pname,
4808 GLsizei bufSize,
4809 const GLint *params)
4810{
4811 if (!ValidateRobustEntryPoint(context, bufSize))
4812 {
4813 return false;
4814 }
4815
4816 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4817}
4818
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004819bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4820 GLuint sampler,
4821 GLenum pname,
4822 GLsizei bufSize,
4823 const GLint *param)
4824{
4825 UNIMPLEMENTED();
4826 return false;
4827}
4828
4829bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4830 GLuint sampler,
4831 GLenum pname,
4832 GLsizei bufSize,
4833 const GLuint *param)
4834{
4835 UNIMPLEMENTED();
4836 return false;
4837}
4838
Geoff Lang0b031062016-10-13 14:30:04 -04004839bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4840 GLuint index,
4841 GLenum pname,
4842 GLsizei bufSize,
4843 GLsizei *length,
4844 GLfloat *params)
4845{
4846 if (!ValidateRobustEntryPoint(context, bufSize))
4847 {
4848 return false;
4849 }
4850
Brandon Jonesd1049182018-03-28 10:02:20 -07004851 GLsizei writeLength = 0;
4852
4853 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004854 {
4855 return false;
4856 }
4857
Brandon Jonesd1049182018-03-28 10:02:20 -07004858 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004859 {
4860 return false;
4861 }
4862
Brandon Jonesd1049182018-03-28 10:02:20 -07004863 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004864 return true;
4865}
4866
Geoff Lang0b031062016-10-13 14:30:04 -04004867bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4868 GLuint index,
4869 GLenum pname,
4870 GLsizei bufSize,
4871 GLsizei *length,
4872 GLint *params)
4873{
4874 if (!ValidateRobustEntryPoint(context, bufSize))
4875 {
4876 return false;
4877 }
4878
Brandon Jonesd1049182018-03-28 10:02:20 -07004879 GLsizei writeLength = 0;
4880
4881 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004882 {
4883 return false;
4884 }
4885
Brandon Jonesd1049182018-03-28 10:02:20 -07004886 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004887 {
4888 return false;
4889 }
4890
Brandon Jonesd1049182018-03-28 10:02:20 -07004891 SetRobustLengthParam(length, writeLength);
4892
Geoff Lang0b031062016-10-13 14:30:04 -04004893 return true;
4894}
4895
Geoff Lang0b031062016-10-13 14:30:04 -04004896bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4897 GLuint index,
4898 GLenum pname,
4899 GLsizei bufSize,
4900 GLsizei *length,
4901 void **pointer)
4902{
4903 if (!ValidateRobustEntryPoint(context, bufSize))
4904 {
4905 return false;
4906 }
4907
Brandon Jonesd1049182018-03-28 10:02:20 -07004908 GLsizei writeLength = 0;
4909
4910 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004911 {
4912 return false;
4913 }
4914
Brandon Jonesd1049182018-03-28 10:02:20 -07004915 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004916 {
4917 return false;
4918 }
4919
Brandon Jonesd1049182018-03-28 10:02:20 -07004920 SetRobustLengthParam(length, writeLength);
4921
Geoff Lang0b031062016-10-13 14:30:04 -04004922 return true;
4923}
4924
Geoff Lang0b031062016-10-13 14:30:04 -04004925bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4926 GLuint index,
4927 GLenum pname,
4928 GLsizei bufSize,
4929 GLsizei *length,
4930 GLint *params)
4931{
4932 if (!ValidateRobustEntryPoint(context, bufSize))
4933 {
4934 return false;
4935 }
4936
Brandon Jonesd1049182018-03-28 10:02:20 -07004937 GLsizei writeLength = 0;
4938
4939 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004940 {
4941 return false;
4942 }
4943
Brandon Jonesd1049182018-03-28 10:02:20 -07004944 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004945 {
4946 return false;
4947 }
4948
Brandon Jonesd1049182018-03-28 10:02:20 -07004949 SetRobustLengthParam(length, writeLength);
4950
Geoff Lang0b031062016-10-13 14:30:04 -04004951 return true;
4952}
4953
Geoff Lang0b031062016-10-13 14:30:04 -04004954bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4955 GLuint index,
4956 GLenum pname,
4957 GLsizei bufSize,
4958 GLsizei *length,
4959 GLuint *params)
4960{
4961 if (!ValidateRobustEntryPoint(context, bufSize))
4962 {
4963 return false;
4964 }
4965
Brandon Jonesd1049182018-03-28 10:02:20 -07004966 GLsizei writeLength = 0;
4967
4968 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004969 {
4970 return false;
4971 }
4972
Brandon Jonesd1049182018-03-28 10:02:20 -07004973 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004974 {
4975 return false;
4976 }
4977
Brandon Jonesd1049182018-03-28 10:02:20 -07004978 SetRobustLengthParam(length, writeLength);
4979
Geoff Lang0b031062016-10-13 14:30:04 -04004980 return true;
4981}
4982
Geoff Lang6899b872016-10-14 11:30:13 -04004983bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4984 GLuint program,
4985 GLuint uniformBlockIndex,
4986 GLenum pname,
4987 GLsizei bufSize,
4988 GLsizei *length,
4989 GLint *params)
4990{
4991 if (!ValidateRobustEntryPoint(context, bufSize))
4992 {
4993 return false;
4994 }
4995
Brandon Jonesd1049182018-03-28 10:02:20 -07004996 GLsizei writeLength = 0;
4997
4998 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4999 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005000 {
5001 return false;
5002 }
5003
Brandon Jonesd1049182018-03-28 10:02:20 -07005004 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005005 {
5006 return false;
5007 }
5008
Brandon Jonesd1049182018-03-28 10:02:20 -07005009 SetRobustLengthParam(length, writeLength);
5010
Geoff Lang6899b872016-10-14 11:30:13 -04005011 return true;
5012}
5013
Brandon Jones416aaf92018-04-10 08:10:16 -07005014bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005015 GLenum target,
5016 GLenum internalformat,
5017 GLenum pname,
5018 GLsizei bufSize,
5019 GLsizei *length,
5020 GLint *params)
5021{
5022 if (!ValidateRobustEntryPoint(context, bufSize))
5023 {
5024 return false;
5025 }
5026
Brandon Jonesd1049182018-03-28 10:02:20 -07005027 GLsizei numParams = 0;
5028
5029 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5030 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005031 {
5032 return false;
5033 }
5034
Brandon Jonesd1049182018-03-28 10:02:20 -07005035 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005036 {
5037 return false;
5038 }
5039
Brandon Jonesd1049182018-03-28 10:02:20 -07005040 SetRobustLengthParam(length, numParams);
5041
Geoff Lang0a9661f2016-10-20 10:59:20 -07005042 return true;
5043}
5044
Jamie Madill5b772312018-03-08 20:28:32 -05005045bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005046 GLuint attribIndex,
5047 GLint size,
5048 GLenum type,
5049 GLboolean pureInteger)
5050{
5051 const Caps &caps = context->getCaps();
5052 if (attribIndex >= caps.maxVertexAttributes)
5053 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005054 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005055 return false;
5056 }
5057
5058 if (size < 1 || size > 4)
5059 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005060 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005061 return false;
Shao80957d92017-02-20 21:25:59 +08005062 }
5063
5064 switch (type)
5065 {
5066 case GL_BYTE:
5067 case GL_UNSIGNED_BYTE:
5068 case GL_SHORT:
5069 case GL_UNSIGNED_SHORT:
5070 break;
5071
5072 case GL_INT:
5073 case GL_UNSIGNED_INT:
5074 if (context->getClientMajorVersion() < 3)
5075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005076 context->handleError(InvalidEnum()
5077 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005078 return false;
5079 }
5080 break;
5081
5082 case GL_FIXED:
5083 case GL_FLOAT:
5084 if (pureInteger)
5085 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005086 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005087 return false;
5088 }
5089 break;
5090
5091 case GL_HALF_FLOAT:
5092 if (context->getClientMajorVersion() < 3)
5093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005094 context->handleError(InvalidEnum()
5095 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005096 return false;
5097 }
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_INT_2_10_10_10_REV:
5106 case GL_UNSIGNED_INT_2_10_10_10_REV:
5107 if (context->getClientMajorVersion() < 3)
5108 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005109 context->handleError(InvalidEnum()
5110 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005111 return false;
5112 }
5113 if (pureInteger)
5114 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005115 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005116 return false;
5117 }
5118 if (size != 4)
5119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005120 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5121 "UNSIGNED_INT_2_10_10_10_REV and "
5122 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005123 return false;
5124 }
5125 break;
5126
5127 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005129 return false;
5130 }
5131
5132 return true;
5133}
5134
Geoff Lang76e65652017-03-27 14:58:02 -04005135// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5136// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5137// specified clear value and the type of a buffer that is being cleared generates an
5138// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005139bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005140 GLint drawbuffer,
5141 const GLenum *validComponentTypes,
5142 size_t validComponentTypeCount)
5143{
5144 const FramebufferAttachment *attachment =
5145 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5146 if (attachment)
5147 {
5148 GLenum componentType = attachment->getFormat().info->componentType;
5149 const GLenum *end = validComponentTypes + validComponentTypeCount;
5150 if (std::find(validComponentTypes, end, componentType) == end)
5151 {
5152 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005153 InvalidOperation()
5154 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005155 return false;
5156 }
5157 }
5158
5159 return true;
5160}
5161
Jamie Madill5b772312018-03-08 20:28:32 -05005162bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005163{
5164 if (!ValidateRobustEntryPoint(context, dataSize))
5165 {
5166 return false;
5167 }
5168
Jamie Madill43da7c42018-08-01 11:34:49 -04005169 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005170 if (pixelUnpackBuffer == nullptr)
5171 {
5172 if (dataSize < imageSize)
5173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005174 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005175 }
5176 }
5177 return true;
5178}
5179
Jamie Madill5b772312018-03-08 20:28:32 -05005180bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005181 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005182 GLenum pname,
5183 bool pointerVersion,
5184 GLsizei *numParams)
5185{
5186 if (numParams)
5187 {
5188 *numParams = 0;
5189 }
5190
Corentin Walleze4477002017-12-01 14:39:58 -05005191 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005193 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005194 return false;
5195 }
5196
5197 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5198 if (!buffer)
5199 {
5200 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005201 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005202 return false;
5203 }
5204
5205 const Extensions &extensions = context->getExtensions();
5206
5207 switch (pname)
5208 {
5209 case GL_BUFFER_USAGE:
5210 case GL_BUFFER_SIZE:
5211 break;
5212
5213 case GL_BUFFER_ACCESS_OES:
5214 if (!extensions.mapBuffer)
5215 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005216 context->handleError(InvalidEnum()
5217 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005218 return false;
5219 }
5220 break;
5221
5222 case GL_BUFFER_MAPPED:
5223 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5224 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5225 !extensions.mapBufferRange)
5226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005227 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5228 "GL_OES_mapbuffer or "
5229 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005230 return false;
5231 }
5232 break;
5233
5234 case GL_BUFFER_MAP_POINTER:
5235 if (!pointerVersion)
5236 {
5237 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005238 InvalidEnum()
5239 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005240 return false;
5241 }
5242 break;
5243
5244 case GL_BUFFER_ACCESS_FLAGS:
5245 case GL_BUFFER_MAP_OFFSET:
5246 case GL_BUFFER_MAP_LENGTH:
5247 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005249 context->handleError(InvalidEnum()
5250 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005251 return false;
5252 }
5253 break;
5254
5255 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005256 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005257 return false;
5258 }
5259
5260 // All buffer parameter queries return one value.
5261 if (numParams)
5262 {
5263 *numParams = 1;
5264 }
5265
5266 return true;
5267}
5268
5269bool ValidateGetRenderbufferParameterivBase(Context *context,
5270 GLenum target,
5271 GLenum pname,
5272 GLsizei *length)
5273{
5274 if (length)
5275 {
5276 *length = 0;
5277 }
5278
5279 if (target != GL_RENDERBUFFER)
5280 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005281 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005282 return false;
5283 }
5284
5285 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5286 if (renderbuffer == nullptr)
5287 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005288 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005289 return false;
5290 }
5291
5292 switch (pname)
5293 {
5294 case GL_RENDERBUFFER_WIDTH:
5295 case GL_RENDERBUFFER_HEIGHT:
5296 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5297 case GL_RENDERBUFFER_RED_SIZE:
5298 case GL_RENDERBUFFER_GREEN_SIZE:
5299 case GL_RENDERBUFFER_BLUE_SIZE:
5300 case GL_RENDERBUFFER_ALPHA_SIZE:
5301 case GL_RENDERBUFFER_DEPTH_SIZE:
5302 case GL_RENDERBUFFER_STENCIL_SIZE:
5303 break;
5304
5305 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5306 if (!context->getExtensions().framebufferMultisample)
5307 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005308 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005309 return false;
5310 }
5311 break;
5312
5313 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005314 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005315 return false;
5316 }
5317
5318 if (length)
5319 {
5320 *length = 1;
5321 }
5322 return true;
5323}
5324
5325bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5326{
5327 if (length)
5328 {
5329 *length = 0;
5330 }
5331
5332 if (GetValidShader(context, shader) == nullptr)
5333 {
5334 return false;
5335 }
5336
5337 switch (pname)
5338 {
5339 case GL_SHADER_TYPE:
5340 case GL_DELETE_STATUS:
5341 case GL_COMPILE_STATUS:
5342 case GL_INFO_LOG_LENGTH:
5343 case GL_SHADER_SOURCE_LENGTH:
5344 break;
5345
5346 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5347 if (!context->getExtensions().translatedShaderSource)
5348 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005349 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005350 return false;
5351 }
5352 break;
5353
5354 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005355 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005356 return false;
5357 }
5358
5359 if (length)
5360 {
5361 *length = 1;
5362 }
5363 return true;
5364}
5365
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005366bool ValidateGetTexParameterBase(Context *context,
5367 TextureType target,
5368 GLenum pname,
5369 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005370{
5371 if (length)
5372 {
5373 *length = 0;
5374 }
5375
5376 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5377 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005378 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005379 return false;
5380 }
5381
5382 if (context->getTargetTexture(target) == nullptr)
5383 {
5384 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 return false;
5387 }
5388
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005389 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5390 {
5391 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5392 return false;
5393 }
5394
Jamie Madillbe849e42017-05-02 15:49:00 -04005395 switch (pname)
5396 {
5397 case GL_TEXTURE_MAG_FILTER:
5398 case GL_TEXTURE_MIN_FILTER:
5399 case GL_TEXTURE_WRAP_S:
5400 case GL_TEXTURE_WRAP_T:
5401 break;
5402
5403 case GL_TEXTURE_USAGE_ANGLE:
5404 if (!context->getExtensions().textureUsage)
5405 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005406 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005407 return false;
5408 }
5409 break;
5410
5411 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005412 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005413 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005414 return false;
5415 }
5416 break;
5417
5418 case GL_TEXTURE_IMMUTABLE_FORMAT:
5419 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
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_WRAP_R:
5427 case GL_TEXTURE_IMMUTABLE_LEVELS:
5428 case GL_TEXTURE_SWIZZLE_R:
5429 case GL_TEXTURE_SWIZZLE_G:
5430 case GL_TEXTURE_SWIZZLE_B:
5431 case GL_TEXTURE_SWIZZLE_A:
5432 case GL_TEXTURE_BASE_LEVEL:
5433 case GL_TEXTURE_MAX_LEVEL:
5434 case GL_TEXTURE_MIN_LOD:
5435 case GL_TEXTURE_MAX_LOD:
5436 case GL_TEXTURE_COMPARE_MODE:
5437 case GL_TEXTURE_COMPARE_FUNC:
5438 if (context->getClientMajorVersion() < 3)
5439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005440 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 return false;
5442 }
5443 break;
5444
5445 case GL_TEXTURE_SRGB_DECODE_EXT:
5446 if (!context->getExtensions().textureSRGBDecode)
5447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005448 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005449 return false;
5450 }
5451 break;
5452
Yunchao Hebacaa712018-01-30 14:01:39 +08005453 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5454 if (context->getClientVersion() < Version(3, 1))
5455 {
5456 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5457 return false;
5458 }
5459 break;
5460
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005461 case GL_GENERATE_MIPMAP:
5462 case GL_TEXTURE_CROP_RECT_OES:
5463 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5464 // after GL_OES_draw_texture functionality implemented
5465 if (context->getClientMajorVersion() > 1)
5466 {
5467 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5468 return false;
5469 }
5470 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005471 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005472 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005473 return false;
5474 }
5475
5476 if (length)
5477 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005478 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005479 }
5480 return true;
5481}
5482
5483bool ValidateGetVertexAttribBase(Context *context,
5484 GLuint index,
5485 GLenum pname,
5486 GLsizei *length,
5487 bool pointer,
5488 bool pureIntegerEntryPoint)
5489{
5490 if (length)
5491 {
5492 *length = 0;
5493 }
5494
5495 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005497 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005498 return false;
5499 }
5500
5501 if (index >= context->getCaps().maxVertexAttributes)
5502 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005503 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005504 return false;
5505 }
5506
5507 if (pointer)
5508 {
5509 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5510 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005511 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005512 return false;
5513 }
5514 }
5515 else
5516 {
5517 switch (pname)
5518 {
5519 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5520 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5521 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5522 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5523 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5524 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5525 case GL_CURRENT_VERTEX_ATTRIB:
5526 break;
5527
5528 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5529 static_assert(
5530 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5531 "ANGLE extension enums not equal to GL enums.");
5532 if (context->getClientMajorVersion() < 3 &&
5533 !context->getExtensions().instancedArrays)
5534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005535 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5536 "requires OpenGL ES 3.0 or "
5537 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005538 return false;
5539 }
5540 break;
5541
5542 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5543 if (context->getClientMajorVersion() < 3)
5544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005545 context->handleError(
5546 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005547 return false;
5548 }
5549 break;
5550
5551 case GL_VERTEX_ATTRIB_BINDING:
5552 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5553 if (context->getClientVersion() < ES_3_1)
5554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005555 context->handleError(InvalidEnum()
5556 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005557 return false;
5558 }
5559 break;
5560
5561 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005562 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005563 return false;
5564 }
5565 }
5566
5567 if (length)
5568 {
5569 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5570 {
5571 *length = 4;
5572 }
5573 else
5574 {
5575 *length = 1;
5576 }
5577 }
5578
5579 return true;
5580}
5581
Jamie Madill4928b7c2017-06-20 12:57:39 -04005582bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005583 GLint x,
5584 GLint y,
5585 GLsizei width,
5586 GLsizei height,
5587 GLenum format,
5588 GLenum type,
5589 GLsizei bufSize,
5590 GLsizei *length,
5591 GLsizei *columns,
5592 GLsizei *rows,
5593 void *pixels)
5594{
5595 if (length != nullptr)
5596 {
5597 *length = 0;
5598 }
5599 if (rows != nullptr)
5600 {
5601 *rows = 0;
5602 }
5603 if (columns != nullptr)
5604 {
5605 *columns = 0;
5606 }
5607
5608 if (width < 0 || height < 0)
5609 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005610 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005611 return false;
5612 }
5613
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005614 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005615
Jamie Madill427064d2018-04-13 16:20:34 -04005616 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005617 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005618 return false;
5619 }
5620
Jamie Madille98b1b52018-03-08 09:47:23 -05005621 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005622 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005623 return false;
5624 }
5625
Jamie Madill690c8eb2018-03-12 15:20:03 -04005626 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005627 ASSERT(framebuffer);
5628
5629 if (framebuffer->getReadBufferState() == GL_NONE)
5630 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005631 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005632 return false;
5633 }
5634
5635 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5636 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5637 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5638 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5639 // situation is an application error that would lead to a crash in ANGLE.
5640 if (readBuffer == nullptr)
5641 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005642 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005643 return false;
5644 }
5645
Martin Radev28031682017-07-28 14:47:56 +03005646 // ANGLE_multiview, Revision 1:
5647 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005648 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5649 // in the current read framebuffer is more than one.
5650 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005651 {
5652 context->handleError(InvalidFramebufferOperation()
5653 << "Attempting to read from a multi-view framebuffer.");
5654 return false;
5655 }
5656
Geoff Lang280ba992017-04-18 16:30:58 -04005657 if (context->getExtensions().webglCompatibility)
5658 {
5659 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5660 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5661 // and type before validating the combination of format and type. However, the
5662 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5663 // verifies that GL_INVALID_OPERATION is generated.
5664 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5665 // dEQP/WebGL.
5666 if (!ValidReadPixelsFormatEnum(context, format))
5667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005668 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005669 return false;
5670 }
5671
5672 if (!ValidReadPixelsTypeEnum(context, type))
5673 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005674 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005675 return false;
5676 }
5677 }
5678
Jamie Madill690c8eb2018-03-12 15:20:03 -04005679 GLenum currentFormat = GL_NONE;
5680 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5681
5682 GLenum currentType = GL_NONE;
5683 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5684
Jamie Madillbe849e42017-05-02 15:49:00 -04005685 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5686
5687 bool validFormatTypeCombination =
5688 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5689
5690 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5691 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005693 return false;
5694 }
5695
5696 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005697 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005698 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5699 {
5700 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005701 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005702 return false;
5703 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005704 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5705 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5706 {
5707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5708 return false;
5709 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005710
5711 // .. the data would be packed to the buffer object such that the memory writes required
5712 // would exceed the data store size.
5713 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005714 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005715 const auto &pack = context->getGLState().getPackState();
5716
Jamie Madillca2ff382018-07-11 09:01:17 -04005717 GLuint endByte = 0;
5718 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005719 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005720 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005721 return false;
5722 }
5723
Jamie Madillbe849e42017-05-02 15:49:00 -04005724 if (bufSize >= 0)
5725 {
5726 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5727 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005728 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005729 return false;
5730 }
5731 }
5732
5733 if (pixelPackBuffer != nullptr)
5734 {
5735 CheckedNumeric<size_t> checkedEndByte(endByte);
5736 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5737 checkedEndByte += checkedOffset;
5738
5739 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5740 {
5741 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005742 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005743 return false;
5744 }
5745 }
5746
5747 if (pixelPackBuffer == nullptr && length != nullptr)
5748 {
5749 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5750 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005751 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005752 return false;
5753 }
5754
5755 *length = static_cast<GLsizei>(endByte);
5756 }
5757
Geoff Langa953b522018-02-21 16:56:23 -05005758 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005759 angle::CheckedNumeric<int> clippedExtent(length);
5760 if (start < 0)
5761 {
5762 // "subtract" the area that is less than 0
5763 clippedExtent += start;
5764 }
5765
Geoff Langa953b522018-02-21 16:56:23 -05005766 angle::CheckedNumeric<int> readExtent = start;
5767 readExtent += length;
5768 if (!readExtent.IsValid())
5769 {
5770 return false;
5771 }
5772
5773 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005774 {
5775 // Subtract the region to the right of the read buffer
5776 clippedExtent -= (readExtent - bufferSize);
5777 }
5778
5779 if (!clippedExtent.IsValid())
5780 {
Geoff Langa953b522018-02-21 16:56:23 -05005781 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005782 }
5783
Geoff Langa953b522018-02-21 16:56:23 -05005784 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5785 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005786 };
5787
Geoff Langa953b522018-02-21 16:56:23 -05005788 GLsizei writtenColumns = 0;
5789 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5790 {
5791 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5792 return false;
5793 }
5794
5795 GLsizei writtenRows = 0;
5796 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5797 {
5798 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5799 return false;
5800 }
5801
Jamie Madillbe849e42017-05-02 15:49:00 -04005802 if (columns != nullptr)
5803 {
Geoff Langa953b522018-02-21 16:56:23 -05005804 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005805 }
5806
5807 if (rows != nullptr)
5808 {
Geoff Langa953b522018-02-21 16:56:23 -05005809 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005810 }
5811
5812 return true;
5813}
5814
5815template <typename ParamType>
5816bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005817 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005818 GLenum pname,
5819 GLsizei bufSize,
5820 const ParamType *params)
5821{
5822 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5823 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005825 return false;
5826 }
5827
5828 if (context->getTargetTexture(target) == nullptr)
5829 {
5830 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005831 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005832 return false;
5833 }
5834
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005835 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005836 if (bufSize >= 0 && bufSize < minBufSize)
5837 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005838 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005839 return false;
5840 }
5841
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005842 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5843 {
5844 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5845 return false;
5846 }
5847
Jamie Madillbe849e42017-05-02 15:49:00 -04005848 switch (pname)
5849 {
5850 case GL_TEXTURE_WRAP_R:
5851 case GL_TEXTURE_SWIZZLE_R:
5852 case GL_TEXTURE_SWIZZLE_G:
5853 case GL_TEXTURE_SWIZZLE_B:
5854 case GL_TEXTURE_SWIZZLE_A:
5855 case GL_TEXTURE_BASE_LEVEL:
5856 case GL_TEXTURE_MAX_LEVEL:
5857 case GL_TEXTURE_COMPARE_MODE:
5858 case GL_TEXTURE_COMPARE_FUNC:
5859 case GL_TEXTURE_MIN_LOD:
5860 case GL_TEXTURE_MAX_LOD:
5861 if (context->getClientMajorVersion() < 3)
5862 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005863 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005864 return false;
5865 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005866 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005868 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5869 "available without "
5870 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005871 return false;
5872 }
5873 break;
5874
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005875 case GL_GENERATE_MIPMAP:
5876 case GL_TEXTURE_CROP_RECT_OES:
5877 if (context->getClientMajorVersion() > 1)
5878 {
5879 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5880 return false;
5881 }
5882 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005883 default:
5884 break;
5885 }
5886
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005887 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005888 {
5889 switch (pname)
5890 {
5891 case GL_TEXTURE_MIN_FILTER:
5892 case GL_TEXTURE_MAG_FILTER:
5893 case GL_TEXTURE_WRAP_S:
5894 case GL_TEXTURE_WRAP_T:
5895 case GL_TEXTURE_WRAP_R:
5896 case GL_TEXTURE_MIN_LOD:
5897 case GL_TEXTURE_MAX_LOD:
5898 case GL_TEXTURE_COMPARE_MODE:
5899 case GL_TEXTURE_COMPARE_FUNC:
5900 context->handleError(InvalidEnum()
5901 << "Invalid parameter for 2D multisampled textures.");
5902 return false;
5903 }
5904 }
5905
Jamie Madillbe849e42017-05-02 15:49:00 -04005906 switch (pname)
5907 {
5908 case GL_TEXTURE_WRAP_S:
5909 case GL_TEXTURE_WRAP_T:
5910 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005911 {
5912 bool restrictedWrapModes =
5913 target == TextureType::External || target == TextureType::Rectangle;
5914 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005915 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005916 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005917 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005918 }
5919 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005920
5921 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005922 {
5923 bool restrictedMinFilter =
5924 target == TextureType::External || target == TextureType::Rectangle;
5925 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005926 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005927 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005928 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005929 }
5930 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005931
5932 case GL_TEXTURE_MAG_FILTER:
5933 if (!ValidateTextureMagFilterValue(context, params))
5934 {
5935 return false;
5936 }
5937 break;
5938
5939 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005940 if (!context->getExtensions().textureUsage)
5941 {
5942 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5943 return false;
5944 }
5945
Jamie Madillbe849e42017-05-02 15:49:00 -04005946 switch (ConvertToGLenum(params[0]))
5947 {
5948 case GL_NONE:
5949 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5950 break;
5951
5952 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005953 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005954 return false;
5955 }
5956 break;
5957
5958 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005959 {
5960 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5961 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005962 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005963 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005964 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005965 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5966 }
5967 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005968
5969 case GL_TEXTURE_MIN_LOD:
5970 case GL_TEXTURE_MAX_LOD:
5971 // any value is permissible
5972 break;
5973
5974 case GL_TEXTURE_COMPARE_MODE:
5975 if (!ValidateTextureCompareModeValue(context, params))
5976 {
5977 return false;
5978 }
5979 break;
5980
5981 case GL_TEXTURE_COMPARE_FUNC:
5982 if (!ValidateTextureCompareFuncValue(context, params))
5983 {
5984 return false;
5985 }
5986 break;
5987
5988 case GL_TEXTURE_SWIZZLE_R:
5989 case GL_TEXTURE_SWIZZLE_G:
5990 case GL_TEXTURE_SWIZZLE_B:
5991 case GL_TEXTURE_SWIZZLE_A:
5992 switch (ConvertToGLenum(params[0]))
5993 {
5994 case GL_RED:
5995 case GL_GREEN:
5996 case GL_BLUE:
5997 case GL_ALPHA:
5998 case GL_ZERO:
5999 case GL_ONE:
6000 break;
6001
6002 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006003 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006004 return false;
6005 }
6006 break;
6007
6008 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006009 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006011 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006012 return false;
6013 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006014 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006016 context->handleError(InvalidOperation()
6017 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006018 return false;
6019 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006020 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006021 {
6022 context->handleError(InvalidOperation()
6023 << "Base level must be 0 for multisampled textures.");
6024 return false;
6025 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006026 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006027 {
6028 context->handleError(InvalidOperation()
6029 << "Base level must be 0 for rectangle textures.");
6030 return false;
6031 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006032 break;
6033
6034 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006035 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006036 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006037 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006038 return false;
6039 }
6040 break;
6041
6042 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6043 if (context->getClientVersion() < Version(3, 1))
6044 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006045 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006046 return false;
6047 }
6048 switch (ConvertToGLenum(params[0]))
6049 {
6050 case GL_DEPTH_COMPONENT:
6051 case GL_STENCIL_INDEX:
6052 break;
6053
6054 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006055 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006056 return false;
6057 }
6058 break;
6059
6060 case GL_TEXTURE_SRGB_DECODE_EXT:
6061 if (!ValidateTextureSRGBDecodeValue(context, params))
6062 {
6063 return false;
6064 }
6065 break;
6066
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006067 case GL_GENERATE_MIPMAP:
6068 case GL_TEXTURE_CROP_RECT_OES:
6069 if (context->getClientMajorVersion() > 1)
6070 {
6071 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6072 return false;
6073 }
6074 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006075 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006076 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006077 return false;
6078 }
6079
6080 return true;
6081}
6082
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006083template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6084template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006085
Jamie Madill5b772312018-03-08 20:28:32 -05006086bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006087{
6088 if (index >= MAX_VERTEX_ATTRIBS)
6089 {
6090 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6091 return false;
6092 }
6093
6094 return true;
6095}
6096
6097bool ValidateGetActiveUniformBlockivBase(Context *context,
6098 GLuint program,
6099 GLuint uniformBlockIndex,
6100 GLenum pname,
6101 GLsizei *length)
6102{
6103 if (length)
6104 {
6105 *length = 0;
6106 }
6107
6108 if (context->getClientMajorVersion() < 3)
6109 {
6110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6111 return false;
6112 }
6113
6114 Program *programObject = GetValidProgram(context, program);
6115 if (!programObject)
6116 {
6117 return false;
6118 }
6119
6120 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6121 {
6122 context->handleError(InvalidValue()
6123 << "uniformBlockIndex exceeds active uniform block count.");
6124 return false;
6125 }
6126
6127 switch (pname)
6128 {
6129 case GL_UNIFORM_BLOCK_BINDING:
6130 case GL_UNIFORM_BLOCK_DATA_SIZE:
6131 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6132 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6133 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6134 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6135 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6136 break;
6137
6138 default:
6139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6140 return false;
6141 }
6142
6143 if (length)
6144 {
6145 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6146 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006147 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006148 programObject->getUniformBlockByIndex(uniformBlockIndex);
6149 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6150 }
6151 else
6152 {
6153 *length = 1;
6154 }
6155 }
6156
6157 return true;
6158}
6159
Jamie Madill9696d072017-08-26 23:19:57 -04006160template <typename ParamType>
6161bool ValidateSamplerParameterBase(Context *context,
6162 GLuint sampler,
6163 GLenum pname,
6164 GLsizei bufSize,
6165 ParamType *params)
6166{
6167 if (context->getClientMajorVersion() < 3)
6168 {
6169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6170 return false;
6171 }
6172
6173 if (!context->isSampler(sampler))
6174 {
6175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6176 return false;
6177 }
6178
6179 const GLsizei minBufSize = 1;
6180 if (bufSize >= 0 && bufSize < minBufSize)
6181 {
6182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6183 return false;
6184 }
6185
6186 switch (pname)
6187 {
6188 case GL_TEXTURE_WRAP_S:
6189 case GL_TEXTURE_WRAP_T:
6190 case GL_TEXTURE_WRAP_R:
6191 if (!ValidateTextureWrapModeValue(context, params, false))
6192 {
6193 return false;
6194 }
6195 break;
6196
6197 case GL_TEXTURE_MIN_FILTER:
6198 if (!ValidateTextureMinFilterValue(context, params, false))
6199 {
6200 return false;
6201 }
6202 break;
6203
6204 case GL_TEXTURE_MAG_FILTER:
6205 if (!ValidateTextureMagFilterValue(context, params))
6206 {
6207 return false;
6208 }
6209 break;
6210
6211 case GL_TEXTURE_MIN_LOD:
6212 case GL_TEXTURE_MAX_LOD:
6213 // any value is permissible
6214 break;
6215
6216 case GL_TEXTURE_COMPARE_MODE:
6217 if (!ValidateTextureCompareModeValue(context, params))
6218 {
6219 return false;
6220 }
6221 break;
6222
6223 case GL_TEXTURE_COMPARE_FUNC:
6224 if (!ValidateTextureCompareFuncValue(context, params))
6225 {
6226 return false;
6227 }
6228 break;
6229
6230 case GL_TEXTURE_SRGB_DECODE_EXT:
6231 if (!ValidateTextureSRGBDecodeValue(context, params))
6232 {
6233 return false;
6234 }
6235 break;
6236
Luc Ferron1b1a8642018-01-23 15:12:01 -05006237 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6238 {
6239 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6240 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6241 {
6242 return false;
6243 }
6244 }
6245 break;
6246
Jamie Madill9696d072017-08-26 23:19:57 -04006247 default:
6248 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6249 return false;
6250 }
6251
6252 return true;
6253}
6254
6255template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6256template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6257
6258bool ValidateGetSamplerParameterBase(Context *context,
6259 GLuint sampler,
6260 GLenum pname,
6261 GLsizei *length)
6262{
6263 if (length)
6264 {
6265 *length = 0;
6266 }
6267
6268 if (context->getClientMajorVersion() < 3)
6269 {
6270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6271 return false;
6272 }
6273
6274 if (!context->isSampler(sampler))
6275 {
6276 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6277 return false;
6278 }
6279
6280 switch (pname)
6281 {
6282 case GL_TEXTURE_WRAP_S:
6283 case GL_TEXTURE_WRAP_T:
6284 case GL_TEXTURE_WRAP_R:
6285 case GL_TEXTURE_MIN_FILTER:
6286 case GL_TEXTURE_MAG_FILTER:
6287 case GL_TEXTURE_MIN_LOD:
6288 case GL_TEXTURE_MAX_LOD:
6289 case GL_TEXTURE_COMPARE_MODE:
6290 case GL_TEXTURE_COMPARE_FUNC:
6291 break;
6292
Luc Ferron1b1a8642018-01-23 15:12:01 -05006293 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6294 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6295 {
6296 return false;
6297 }
6298 break;
6299
Jamie Madill9696d072017-08-26 23:19:57 -04006300 case GL_TEXTURE_SRGB_DECODE_EXT:
6301 if (!context->getExtensions().textureSRGBDecode)
6302 {
6303 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6304 return false;
6305 }
6306 break;
6307
6308 default:
6309 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6310 return false;
6311 }
6312
6313 if (length)
6314 {
6315 *length = 1;
6316 }
6317 return true;
6318}
6319
6320bool ValidateGetInternalFormativBase(Context *context,
6321 GLenum target,
6322 GLenum internalformat,
6323 GLenum pname,
6324 GLsizei bufSize,
6325 GLsizei *numParams)
6326{
6327 if (numParams)
6328 {
6329 *numParams = 0;
6330 }
6331
6332 if (context->getClientMajorVersion() < 3)
6333 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006334 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006335 return false;
6336 }
6337
6338 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006339 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006340 {
6341 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6342 return false;
6343 }
6344
6345 switch (target)
6346 {
6347 case GL_RENDERBUFFER:
6348 break;
6349
6350 case GL_TEXTURE_2D_MULTISAMPLE:
6351 if (context->getClientVersion() < ES_3_1)
6352 {
6353 context->handleError(InvalidOperation()
6354 << "Texture target requires at least OpenGL ES 3.1.");
6355 return false;
6356 }
6357 break;
6358
6359 default:
6360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6361 return false;
6362 }
6363
6364 if (bufSize < 0)
6365 {
6366 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6367 return false;
6368 }
6369
6370 GLsizei maxWriteParams = 0;
6371 switch (pname)
6372 {
6373 case GL_NUM_SAMPLE_COUNTS:
6374 maxWriteParams = 1;
6375 break;
6376
6377 case GL_SAMPLES:
6378 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6379 break;
6380
6381 default:
6382 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6383 return false;
6384 }
6385
6386 if (numParams)
6387 {
6388 // glGetInternalFormativ will not overflow bufSize
6389 *numParams = std::min(bufSize, maxWriteParams);
6390 }
6391
6392 return true;
6393}
6394
Jamie Madille98b1b52018-03-08 09:47:23 -05006395bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6396{
Jamie Madill427064d2018-04-13 16:20:34 -04006397 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006398 {
6399 context->handleError(InvalidOperation());
6400 return false;
6401 }
6402 return true;
6403}
6404
Lingfeng Yang038dd532018-03-29 17:31:52 -07006405bool ValidateMultitextureUnit(Context *context, GLenum texture)
6406{
6407 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6408 {
6409 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6410 return false;
6411 }
6412 return true;
6413}
6414
Jamie Madillc29968b2016-01-20 11:17:23 -05006415} // namespace gl