blob: 11da45be10881aceb5800fc2692b352989f64c6b [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:
Olli Etuahof2ed2992018-10-04 13:54:42 +030059 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
60 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
61 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
62 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
Luc Ferron9dbaeba2018-02-01 07:26:59 -050063 return true;
jchen10a99ed552017-09-22 08:10:32 +080064
Luc Ferron9dbaeba2018-02-01 07:26:59 -050065 default:
66 return false;
67 }
68}
69bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
70{
71 // Compressed sub textures have additional formats that requires exact size.
72 // ES 3.1, Section 8.7, Page 171
73 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
74 IsETC2EACFormat(internalFormat);
75}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030076
77bool DifferenceCanOverflow(GLint a, GLint b)
78{
79 CheckedNumeric<GLint> checkedA(a);
80 checkedA -= b;
81 // Use negation to make sure that the difference can't overflow regardless of the order.
82 checkedA = -checkedA;
83 return !checkedA.IsValid();
84}
85
Jamie Madill16e28fd2018-09-12 11:03:05 -040086bool ValidateDrawAttribsImpl(Context *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040087{
Jamie Madill51af38b2018-04-15 08:50:56 -040088 // If we're drawing zero vertices, we have enough data.
Jamie Madill2da53562018-08-01 11:34:47 -040089 ASSERT(primcount > 0);
Jamie Madill51af38b2018-04-15 08:50:56 -040090
Jamie Madill88602e62018-08-08 12:49:30 -040091 // An overflow can happen when adding the offset. Check against a special constant.
92 if (context->getStateCache().getNonInstancedVertexElementLimit() ==
93 VertexAttribute::kIntegerOverflow ||
94 context->getStateCache().getInstancedVertexElementLimit() ==
95 VertexAttribute::kIntegerOverflow)
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040096 {
97 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
98 return false;
99 }
100
101 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
102 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
104 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400105}
106
Jamie Madill16e28fd2018-09-12 11:03:05 -0400107ANGLE_INLINE bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
108{
109 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
110 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
111 {
112 return true;
113 }
114 else
115 {
116 return ValidateDrawAttribsImpl(context, primcount, maxVertex);
117 }
118}
119
Jamie Madill5b772312018-03-08 20:28:32 -0500120bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400121{
122 switch (type)
123 {
124 // Types referenced in Table 3.4 of the ES 2.0.25 spec
125 case GL_UNSIGNED_BYTE:
126 case GL_UNSIGNED_SHORT_4_4_4_4:
127 case GL_UNSIGNED_SHORT_5_5_5_1:
128 case GL_UNSIGNED_SHORT_5_6_5:
129 return context->getClientVersion() >= ES_2_0;
130
131 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
132 case GL_BYTE:
133 case GL_INT:
134 case GL_SHORT:
135 case GL_UNSIGNED_INT:
136 case GL_UNSIGNED_INT_10F_11F_11F_REV:
137 case GL_UNSIGNED_INT_24_8:
138 case GL_UNSIGNED_INT_2_10_10_10_REV:
139 case GL_UNSIGNED_INT_5_9_9_9_REV:
140 case GL_UNSIGNED_SHORT:
141 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
142 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
143 return context->getClientVersion() >= ES_3_0;
144
145 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400146 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
147 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400148
149 case GL_HALF_FLOAT:
150 return context->getClientVersion() >= ES_3_0 ||
151 context->getExtensions().textureHalfFloat;
152
153 case GL_HALF_FLOAT_OES:
154 return context->getExtensions().colorBufferHalfFloat;
155
156 default:
157 return false;
158 }
159}
160
Jamie Madill5b772312018-03-08 20:28:32 -0500161bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400162{
163 switch (format)
164 {
165 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
166 case GL_RGBA:
167 case GL_RGB:
168 case GL_ALPHA:
169 return context->getClientVersion() >= ES_2_0;
170
171 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
172 case GL_RG:
173 case GL_RED:
174 case GL_RGBA_INTEGER:
175 case GL_RGB_INTEGER:
176 case GL_RG_INTEGER:
177 case GL_RED_INTEGER:
178 return context->getClientVersion() >= ES_3_0;
179
180 case GL_SRGB_ALPHA_EXT:
181 case GL_SRGB_EXT:
182 return context->getExtensions().sRGB;
183
184 case GL_BGRA_EXT:
185 return context->getExtensions().readFormatBGRA;
186
187 default:
188 return false;
189 }
190}
191
Jamie Madill5b772312018-03-08 20:28:32 -0500192bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400193 GLenum framebufferComponentType,
194 GLenum format,
195 GLenum type)
196{
197 switch (framebufferComponentType)
198 {
199 case GL_UNSIGNED_NORMALIZED:
200 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
201 // ReadPixels with BGRA even if the extension is not present
202 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
203 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
204 type == GL_UNSIGNED_BYTE);
205
206 case GL_SIGNED_NORMALIZED:
207 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
208
209 case GL_INT:
210 return (format == GL_RGBA_INTEGER && type == GL_INT);
211
212 case GL_UNSIGNED_INT:
213 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
214
215 case GL_FLOAT:
216 return (format == GL_RGBA && type == GL_FLOAT);
217
218 default:
219 UNREACHABLE();
220 return false;
221 }
222}
223
Geoff Langc1984ed2016-10-07 12:41:00 -0400224template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400225bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400226{
227 switch (ConvertToGLenum(params[0]))
228 {
229 case GL_CLAMP_TO_EDGE:
230 break;
231
Till Rathmannb8543632018-10-02 19:46:14 +0200232 case GL_CLAMP_TO_BORDER:
233 if (!context->getExtensions().textureBorderClamp)
234 {
235 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
236 return false;
237 }
238 break;
239
Geoff Langc1984ed2016-10-07 12:41:00 -0400240 case GL_REPEAT:
241 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400242 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400243 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400244 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700245 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400246 return false;
247 }
248 break;
249
250 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700251 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400252 return false;
253 }
254
255 return true;
256}
257
258template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400259bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400260{
261 switch (ConvertToGLenum(params[0]))
262 {
263 case GL_NEAREST:
264 case GL_LINEAR:
265 break;
266
267 case GL_NEAREST_MIPMAP_NEAREST:
268 case GL_LINEAR_MIPMAP_NEAREST:
269 case GL_NEAREST_MIPMAP_LINEAR:
270 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400271 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400272 {
273 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700274 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400275 return false;
276 }
277 break;
278
279 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700280 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400281 return false;
282 }
283
284 return true;
285}
286
287template <typename ParamType>
288bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
289{
290 switch (ConvertToGLenum(params[0]))
291 {
292 case GL_NEAREST:
293 case GL_LINEAR:
294 break;
295
296 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700297 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400298 return false;
299 }
300
301 return true;
302}
303
304template <typename ParamType>
305bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
306{
307 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
308 switch (ConvertToGLenum(params[0]))
309 {
310 case GL_NONE:
311 case GL_COMPARE_REF_TO_TEXTURE:
312 break;
313
314 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700315 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400316 return false;
317 }
318
319 return true;
320}
321
322template <typename ParamType>
323bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
324{
325 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
326 switch (ConvertToGLenum(params[0]))
327 {
328 case GL_LEQUAL:
329 case GL_GEQUAL:
330 case GL_LESS:
331 case GL_GREATER:
332 case GL_EQUAL:
333 case GL_NOTEQUAL:
334 case GL_ALWAYS:
335 case GL_NEVER:
336 break;
337
338 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400340 return false;
341 }
342
343 return true;
344}
345
346template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700347bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
348{
349 if (!context->getExtensions().textureSRGBDecode)
350 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700351 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700352 return false;
353 }
354
355 switch (ConvertToGLenum(params[0]))
356 {
357 case GL_DECODE_EXT:
358 case GL_SKIP_DECODE_EXT:
359 break;
360
361 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700362 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700363 return false;
364 }
365
366 return true;
367}
368
Luc Ferron1b1a8642018-01-23 15:12:01 -0500369bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
370{
371 if (!context->getExtensions().textureFilterAnisotropic)
372 {
373 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
374 return false;
375 }
376
377 return true;
378}
379
380bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
381{
382 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
383 {
384 return false;
385 }
386
387 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
388
389 if (paramValue < 1 || paramValue > largest)
390 {
391 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
392 return false;
393 }
394
395 return true;
396}
397
Jamie Madill5b772312018-03-08 20:28:32 -0500398bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400399{
Jamie Madill785e8a02018-10-04 17:42:00 -0400400 const Program *program = context->getGLState().getLinkedProgram(context);
Geoff Lange0cff192017-05-30 13:04:56 -0400401 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
402
Jamie Madille7d80f32018-08-08 15:49:23 -0400403 return ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
404 framebuffer->getDrawBufferTypeMask().to_ulong(),
405 program->getActiveOutputVariables().to_ulong(),
406 framebuffer->getDrawBufferMask().to_ulong());
Geoff Lange0cff192017-05-30 13:04:56 -0400407}
408
Jamie Madill5b772312018-03-08 20:28:32 -0500409bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400410{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700411 const auto &glState = context->getGLState();
Jamie Madill785e8a02018-10-04 17:42:00 -0400412 const Program *program = context->getGLState().getLinkedProgram(context);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400413 const VertexArray *vao = context->getGLState().getVertexArray();
414
Brandon Jonesc405ae72017-12-06 14:15:03 -0800415 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
416 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
417 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
418
419 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
420 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
421 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
422
Jamie Madille7d80f32018-08-08 15:49:23 -0400423 return ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(),
424 vaoAttribTypeBits, program->getAttributesMask().to_ulong(),
425 0xFFFF);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400426}
427
Jamie Madill493f9572018-05-24 19:52:15 -0400428bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
429 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800430{
431 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400432 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800433 {
Jamie Madill493f9572018-05-24 19:52:15 -0400434 case PrimitiveMode::Points:
435 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
436 case PrimitiveMode::Lines:
437 case PrimitiveMode::LineStrip:
438 case PrimitiveMode::LineLoop:
439 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
440 case PrimitiveMode::LinesAdjacency:
441 case PrimitiveMode::LineStripAdjacency:
442 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
443 case PrimitiveMode::Triangles:
444 case PrimitiveMode::TriangleFan:
445 case PrimitiveMode::TriangleStrip:
446 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
447 case PrimitiveMode::TrianglesAdjacency:
448 case PrimitiveMode::TriangleStripAdjacency:
449 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800450 default:
451 UNREACHABLE();
452 return false;
453 }
454}
455
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700456// GLES1 texture parameters are a small subset of the others
457bool IsValidGLES1TextureParameter(GLenum pname)
458{
459 switch (pname)
460 {
461 case GL_TEXTURE_MAG_FILTER:
462 case GL_TEXTURE_MIN_FILTER:
463 case GL_TEXTURE_WRAP_S:
464 case GL_TEXTURE_WRAP_T:
465 case GL_TEXTURE_WRAP_R:
466 case GL_GENERATE_MIPMAP:
467 case GL_TEXTURE_CROP_RECT_OES:
468 return true;
469 default:
470 return false;
471 }
472}
Till Rathmannb8543632018-10-02 19:46:14 +0200473
474unsigned int GetSamplerParameterCount(GLenum pname)
475{
476 return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1;
477}
478
Geoff Langf41a7152016-09-19 15:11:17 -0400479} // anonymous namespace
480
Brandon Jonesd1049182018-03-28 10:02:20 -0700481void SetRobustLengthParam(GLsizei *length, GLsizei value)
482{
483 if (length)
484 {
485 *length = value;
486 }
487}
488
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500489bool IsETC2EACFormat(const GLenum format)
490{
491 // ES 3.1, Table 8.19
492 switch (format)
493 {
494 case GL_COMPRESSED_R11_EAC:
495 case GL_COMPRESSED_SIGNED_R11_EAC:
496 case GL_COMPRESSED_RG11_EAC:
497 case GL_COMPRESSED_SIGNED_RG11_EAC:
498 case GL_COMPRESSED_RGB8_ETC2:
499 case GL_COMPRESSED_SRGB8_ETC2:
500 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
501 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
502 case GL_COMPRESSED_RGBA8_ETC2_EAC:
503 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
504 return true;
505
506 default:
507 return false;
508 }
509}
510
Jamie Madill5b772312018-03-08 20:28:32 -0500511bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400512{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800513 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400514 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800515 case TextureType::_2D:
516 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800517 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400518
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800519 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400520 return context->getExtensions().textureRectangle;
521
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800522 case TextureType::_3D:
523 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800524 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500525
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800526 case TextureType::_2DMultisample:
Yizhou Jiang7818a852018-09-06 15:02:04 +0800527 return (context->getClientVersion() >= Version(3, 1) ||
528 context->getExtensions().textureMultisample);
Olli Etuahod310a432018-08-24 15:40:23 +0300529 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300530 return context->getExtensions().textureStorageMultisample2DArray;
Geoff Lang3b573612016-10-31 14:08:10 -0400531
He Yunchaoced53ae2016-11-29 15:00:51 +0800532 default:
533 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500534 }
Jamie Madill35d15012013-10-07 10:46:37 -0400535}
536
Jamie Madill5b772312018-03-08 20:28:32 -0500537bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500538{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800539 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500540 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800541 case TextureType::_2D:
542 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500543 return true;
544
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800545 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400546 return context->getExtensions().textureRectangle;
547
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500548 default:
549 return false;
550 }
551}
552
Jamie Madill5b772312018-03-08 20:28:32 -0500553bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500554{
555 switch (target)
556 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800557 case TextureType::_3D:
558 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300559 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500560
561 default:
562 return false;
563 }
564}
565
Ian Ewellbda75592016-04-18 17:25:54 -0400566// Most texture GL calls are not compatible with external textures, so we have a separate validation
567// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500568bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400569{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800570 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400571 (context->getExtensions().eglImageExternal ||
572 context->getExtensions().eglStreamConsumerExternal);
573}
574
Shannon Woods4dfed832014-03-17 20:03:39 -0400575// This function differs from ValidTextureTarget in that the target must be
576// usable as the destination of a 2D operation-- so a cube face is valid, but
577// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400578// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500579bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400580{
581 switch (target)
582 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800583 case TextureTarget::_2D:
584 case TextureTarget::CubeMapNegativeX:
585 case TextureTarget::CubeMapNegativeY:
586 case TextureTarget::CubeMapNegativeZ:
587 case TextureTarget::CubeMapPositiveX:
588 case TextureTarget::CubeMapPositiveY:
589 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800590 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800591 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400592 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800593 default:
594 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500595 }
596}
597
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800598bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400599 PrimitiveMode transformFeedbackPrimitiveMode,
600 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800601{
602 ASSERT(context);
603
604 if (!context->getExtensions().geometryShader)
605 {
606 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
607 // that does not match the current transform feedback object's draw mode (if transform
608 // feedback is active), (3.0.2, section 2.14, pg 86)
609 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
610 }
611
612 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400613 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800614 {
Jamie Madill493f9572018-05-24 19:52:15 -0400615 case PrimitiveMode::Points:
616 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
617 case PrimitiveMode::Lines:
618 case PrimitiveMode::LineStrip:
619 case PrimitiveMode::LineLoop:
620 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
621 case PrimitiveMode::Triangles:
622 case PrimitiveMode::TriangleFan:
623 case PrimitiveMode::TriangleStrip:
624 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800625 default:
626 UNREACHABLE();
627 return false;
628 }
629}
630
Jamie Madill5b772312018-03-08 20:28:32 -0500631bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400632 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400633 GLsizei count,
634 GLenum type,
635 const GLvoid *indices,
636 GLsizei primcount)
637{
638 if (primcount < 0)
639 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700640 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400641 return false;
642 }
643
644 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
645 {
646 return false;
647 }
648
Jamie Madill9fdaa492018-02-16 10:52:11 -0500649 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400650}
651
652bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400653 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400654 GLint first,
655 GLsizei count,
656 GLsizei primcount)
657{
658 if (primcount < 0)
659 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700660 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400661 return false;
662 }
663
664 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
665 {
666 return false;
667 }
668
Jamie Madill9fdaa492018-02-16 10:52:11 -0500669 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400670}
671
Jamie Madill5b772312018-03-08 20:28:32 -0500672bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400673{
674 // Verify there is at least one active attribute with a divisor of zero
675 const State &state = context->getGLState();
676
Jamie Madill785e8a02018-10-04 17:42:00 -0400677 Program *program = state.getLinkedProgram(context);
Jamie Madillbe849e42017-05-02 15:49:00 -0400678
679 const auto &attribs = state.getVertexArray()->getVertexAttributes();
680 const auto &bindings = state.getVertexArray()->getVertexBindings();
681 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
682 {
683 const VertexAttribute &attrib = attribs[attributeIndex];
684 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300685 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400686 {
687 return true;
688 }
689 }
690
Brandon Jonesafa75152017-07-21 13:11:29 -0700691 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400692 return false;
693}
694
Jamie Madill5b772312018-03-08 20:28:32 -0500695bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500696{
697 switch (target)
698 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800699 case TextureType::_3D:
700 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800701 return true;
702 default:
703 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400704 }
705}
706
Jamie Madill5b772312018-03-08 20:28:32 -0500707bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800708{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800709 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800710 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800711 case TextureType::_2D:
712 case TextureType::_2DArray:
713 case TextureType::_2DMultisample:
714 case TextureType::CubeMap:
715 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800716 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800717 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400718 return context->getExtensions().textureRectangle;
Olli Etuahod310a432018-08-24 15:40:23 +0300719 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300720 return context->getExtensions().textureStorageMultisample2DArray;
He Yunchao11b038b2016-11-22 21:24:04 +0800721 default:
722 return false;
723 }
724}
725
Jamie Madill5b772312018-03-08 20:28:32 -0500726bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500727{
He Yunchaoced53ae2016-11-29 15:00:51 +0800728 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
729 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400730 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500731
732 switch (target)
733 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800734 case GL_FRAMEBUFFER:
735 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400736
He Yunchaoced53ae2016-11-29 15:00:51 +0800737 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800738 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400739 return (context->getExtensions().framebufferBlit ||
740 context->getClientMajorVersion() >= 3);
741
He Yunchaoced53ae2016-11-29 15:00:51 +0800742 default:
743 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500744 }
745}
746
Jamie Madill5b772312018-03-08 20:28:32 -0500747bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400748{
Jamie Madillc29968b2016-01-20 11:17:23 -0500749 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400750 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800751 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400752 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800753 case TextureType::_2D:
754 case TextureType::_2DArray:
755 case TextureType::_2DMultisample:
Olli Etuahod310a432018-08-24 15:40:23 +0300756 case TextureType::_2DMultisampleArray:
757 // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
758 // level-of-detail" for multisample textures should be. Could maybe make it zero.
Jamie Madillc29968b2016-01-20 11:17:23 -0500759 maxDimension = caps.max2DTextureSize;
760 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800761 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800762 maxDimension = caps.maxCubeMapTextureSize;
763 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800764 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400765 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800766 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800767 maxDimension = caps.max3DTextureSize;
768 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800769 default:
770 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400771 }
772
Jamie Madill43da7c42018-08-01 11:34:49 -0400773 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400774}
775
Jamie Madill5b772312018-03-08 20:28:32 -0500776bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800777 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700778 GLint level,
779 GLsizei width,
780 GLsizei height,
781 GLsizei depth,
782 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400783{
Brandon Jones6cad5662017-06-14 13:25:13 -0700784 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400785 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700786 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400787 return false;
788 }
Austin Kinross08528e12015-10-07 16:24:40 -0700789 // TexSubImage parameters can be NPOT without textureNPOT extension,
790 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500791 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500792 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500793 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400794 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400795 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700796 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400797 return false;
798 }
799
800 if (!ValidMipLevel(context, target, level))
801 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700802 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400803 return false;
804 }
805
806 return true;
807}
808
Geoff Lang966c9402017-04-18 12:38:27 -0400809bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
810{
811 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
812 (size % blockSize == 0);
813}
814
Jamie Madill5b772312018-03-08 20:28:32 -0500815bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500816 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400817 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500818 GLsizei width,
819 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400820{
Jamie Madill43da7c42018-08-01 11:34:49 -0400821 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400822 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400823 {
824 return false;
825 }
826
Geoff Lang966c9402017-04-18 12:38:27 -0400827 if (width < 0 || height < 0)
828 {
829 return false;
830 }
831
832 if (CompressedTextureFormatRequiresExactSize(internalFormat))
833 {
834 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
835 // block size for level 0 but WebGL disallows this.
836 bool smallerThanBlockSizeAllowed =
837 level > 0 || !context->getExtensions().webglCompatibility;
838
839 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
840 smallerThanBlockSizeAllowed) ||
841 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
842 smallerThanBlockSizeAllowed))
843 {
844 return false;
845 }
846 }
847
848 return true;
849}
850
Jamie Madill5b772312018-03-08 20:28:32 -0500851bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400852 GLenum internalFormat,
853 GLint xoffset,
854 GLint yoffset,
855 GLsizei width,
856 GLsizei height,
857 size_t textureWidth,
858 size_t textureHeight)
859{
Jamie Madill43da7c42018-08-01 11:34:49 -0400860 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400861 if (!formatInfo.compressed)
862 {
863 return false;
864 }
865
Geoff Lang44ff5a72017-02-03 15:15:43 -0500866 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400867 {
868 return false;
869 }
870
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500871 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400872 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500873 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400874 yoffset % formatInfo.compressedBlockHeight != 0)
875 {
876 return false;
877 }
878
879 // Allowed to either have data that is a multiple of block size or is smaller than the block
880 // size but fills the entire mip
881 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
882 static_cast<size_t>(width) == textureWidth &&
883 static_cast<size_t>(height) == textureHeight;
884 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
885 (height % formatInfo.compressedBlockHeight) == 0;
886 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400887 {
888 return false;
889 }
890 }
891
Geoff Langd4f180b2013-09-24 13:57:44 -0400892 return true;
893}
894
Jamie Madill5b772312018-03-08 20:28:32 -0500895bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800896 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400897 GLsizei width,
898 GLsizei height,
899 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400900 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400901 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400902 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400903 GLsizei imageSize)
904{
Jamie Madill43da7c42018-08-01 11:34:49 -0400905 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400906 if (pixelUnpackBuffer == nullptr && imageSize < 0)
907 {
908 // Checks are not required
909 return true;
910 }
911
912 // ...the data would be unpacked from the buffer object such that the memory reads required
913 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400914 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400915 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400916 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400917 const auto &unpack = context->getGLState().getUnpackState();
918
Jamie Madill7f232932018-09-12 11:03:06 -0400919 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
920 GLuint endByte = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400921 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400922 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400923 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400924 return false;
925 }
926
Geoff Langff5b2d52016-09-07 11:32:23 -0400927 if (pixelUnpackBuffer)
928 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400929 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400930 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
931 checkedEndByte += checkedOffset;
932
933 if (!checkedEndByte.IsValid() ||
934 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
935 {
936 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400937 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400938 return false;
939 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800940 if (context->getExtensions().webglCompatibility &&
941 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
942 {
943 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
944 PixelUnpackBufferBoundForTransformFeedback);
945 return false;
946 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400947 }
948 else
949 {
950 ASSERT(imageSize >= 0);
951 if (pixels == nullptr && imageSize != 0)
952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500953 context->handleError(InvalidOperation()
954 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400955 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400956 }
957
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400958 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500960 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400961 return false;
962 }
963 }
964
965 return true;
966}
967
Corentin Wallezad3ae902018-03-09 13:40:42 -0500968bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500969{
Geoff Lang37dde692014-01-31 16:34:54 -0500970 switch (queryType)
971 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500972 case QueryType::AnySamples:
973 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400974 return context->getClientMajorVersion() >= 3 ||
975 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500976 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800977 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500978 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800979 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500980 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800981 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500982 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800983 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800984 default:
985 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500986 }
987}
988
Jamie Madill5b772312018-03-08 20:28:32 -0500989bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400990 GLenum type,
991 GLboolean normalized,
992 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400993 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400994 bool pureInteger)
995{
996 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400997 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
998 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
999 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1000 // parameter exceeds 255.
1001 constexpr GLsizei kMaxWebGLStride = 255;
1002 if (stride > kMaxWebGLStride)
1003 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001004 context->handleError(InvalidValue()
1005 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001006 return false;
1007 }
1008
1009 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1010 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1011 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1012 // or an INVALID_OPERATION error is generated.
Frank Henigmand633b152018-10-04 23:34:31 -04001013 angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
1014 size_t typeSize = GetVertexFormatSize(internalType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001015
1016 ASSERT(isPow2(typeSize) && typeSize > 0);
1017 size_t sizeMask = (typeSize - 1);
1018 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1019 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001020 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001021 return false;
1022 }
1023
1024 if ((stride & sizeMask) != 0)
1025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001026 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001027 return false;
1028 }
1029
1030 return true;
1031}
1032
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001033Program *GetValidProgramNoResolve(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001034{
He Yunchaoced53ae2016-11-29 15:00:51 +08001035 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1036 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1037 // or program object and INVALID_OPERATION if the provided name identifies an object
1038 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001039
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001040 Program *validProgram = context->getProgramNoResolveLink(id);
Dian Xiang769769a2015-09-09 15:20:08 -07001041
1042 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001043 {
Dian Xiang769769a2015-09-09 15:20:08 -07001044 if (context->getShader(id))
1045 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001046 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001047 }
1048 else
1049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001050 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001051 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001052 }
Dian Xiang769769a2015-09-09 15:20:08 -07001053
1054 return validProgram;
1055}
1056
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001057Program *GetValidProgram(Context *context, GLuint id)
1058{
1059 Program *program = GetValidProgramNoResolve(context, id);
1060 if (program)
1061 {
Jamie Madill785e8a02018-10-04 17:42:00 -04001062 program->resolveLink(context);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001063 }
1064 return program;
1065}
1066
Jamie Madill5b772312018-03-08 20:28:32 -05001067Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001068{
1069 // See ValidProgram for spec details.
1070
1071 Shader *validShader = context->getShader(id);
1072
1073 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001074 {
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001075 if (context->getProgramNoResolveLink(id))
Dian Xiang769769a2015-09-09 15:20:08 -07001076 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001077 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001078 }
1079 else
1080 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001081 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001082 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001083 }
Dian Xiang769769a2015-09-09 15:20:08 -07001084
1085 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001086}
1087
Jamie Madill43da7c42018-08-01 11:34:49 -04001088bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001089{
Geoff Langfa125c92017-10-24 13:01:46 -04001090 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001091 {
Geoff Langfa125c92017-10-24 13:01:46 -04001092 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1093 {
1094 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1095 return false;
1096 }
Jamie Madillb4472272014-07-03 10:38:55 -04001097
Geoff Langfa125c92017-10-24 13:01:46 -04001098 // Color attachment 0 is validated below because it is always valid
1099 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001100 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001101 {
Geoff Langfa125c92017-10-24 13:01:46 -04001102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001103 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001104 }
1105 }
1106 else
1107 {
1108 switch (attachment)
1109 {
Geoff Langfa125c92017-10-24 13:01:46 -04001110 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 case GL_DEPTH_ATTACHMENT:
1112 case GL_STENCIL_ATTACHMENT:
1113 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001114
He Yunchaoced53ae2016-11-29 15:00:51 +08001115 case GL_DEPTH_STENCIL_ATTACHMENT:
1116 if (!context->getExtensions().webglCompatibility &&
1117 context->getClientMajorVersion() < 3)
1118 {
Geoff Langfa125c92017-10-24 13:01:46 -04001119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
1121 }
1122 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001123
He Yunchaoced53ae2016-11-29 15:00:51 +08001124 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001125 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001126 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001127 }
1128 }
1129
1130 return true;
1131}
1132
Jamie Madill5b772312018-03-08 20:28:32 -05001133bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001134 GLenum target,
1135 GLsizei samples,
1136 GLenum internalformat,
1137 GLsizei width,
1138 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139{
1140 switch (target)
1141 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001142 case GL_RENDERBUFFER:
1143 break;
1144 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001145 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148
1149 if (width < 0 || height < 0 || samples < 0)
1150 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001151 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001152 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001153 }
1154
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001155 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1156 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1157
1158 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001159 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001161 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001162 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001163 }
1164
1165 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1166 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001167 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001168 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001169 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
Geoff Langaae65a42014-05-26 12:43:44 -04001175 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001177 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001178 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001179 }
1180
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001181 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 if (handle == 0)
1183 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001185 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001186 }
1187
1188 return true;
1189}
1190
Jamie Madill43da7c42018-08-01 11:34:49 -04001191bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001192 GLenum target,
1193 GLenum attachment,
1194 GLenum renderbuffertarget,
1195 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001196{
Geoff Lange8afa902017-09-27 15:00:43 -04001197 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001199 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001200 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001201 }
1202
Jamie Madill43da7c42018-08-01 11:34:49 -04001203 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001204
Jamie Madill84115c92015-04-23 15:00:07 -04001205 ASSERT(framebuffer);
1206 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001209 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001210 }
1211
Jamie Madillb4472272014-07-03 10:38:55 -04001212 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001213 {
Jamie Madillb4472272014-07-03 10:38:55 -04001214 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001215 }
1216
Jamie Madillab9d82c2014-01-21 16:38:14 -05001217 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1218 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1219 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1220 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1221 if (renderbuffer != 0)
1222 {
1223 if (!context->getRenderbuffer(renderbuffer))
1224 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001225 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001226 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001227 }
1228 }
1229
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001230 return true;
1231}
1232
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001233bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001234 GLint srcX0,
1235 GLint srcY0,
1236 GLint srcX1,
1237 GLint srcY1,
1238 GLint dstX0,
1239 GLint dstY0,
1240 GLint dstX1,
1241 GLint dstY1,
1242 GLbitfield mask,
1243 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001244{
1245 switch (filter)
1246 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001247 case GL_NEAREST:
1248 break;
1249 case GL_LINEAR:
1250 break;
1251 default:
Olli Etuahof0e3c192018-08-15 13:37:21 +03001252 ANGLE_VALIDATION_ERR(context, InvalidEnum(), BlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 }
1255
1256 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1257 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001258 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001259 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260 }
1261
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1263 // color buffer, leaving only nearest being unfiltered from above
1264 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1265 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001266 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001267 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001268 }
1269
Jamie Madill7f232932018-09-12 11:03:06 -04001270 const auto &glState = context->getGLState();
1271 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1272 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001273
1274 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001276 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001277 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 }
1279
Jamie Madill427064d2018-04-13 16:20:34 -04001280 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001281 {
Jamie Madill48faf802014-11-06 15:27:22 -05001282 return false;
1283 }
1284
Jamie Madill427064d2018-04-13 16:20:34 -04001285 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001286 {
Jamie Madill48faf802014-11-06 15:27:22 -05001287 return false;
1288 }
1289
Qin Jiajiaaef92162018-02-27 13:51:44 +08001290 if (readFramebuffer->id() == drawFramebuffer->id())
1291 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001292 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001293 return false;
1294 }
1295
Jamie Madille98b1b52018-03-08 09:47:23 -05001296 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297 {
Geoff Langb1196682014-07-23 13:47:29 -04001298 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 }
1300
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001301 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1302 // always run it in order to avoid triggering driver bugs.
1303 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1304 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001305 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001306 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1307 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001308 }
1309
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1311
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 if (mask & GL_COLOR_BUFFER_BIT)
1313 {
Jamie Madill7f232932018-09-12 11:03:06 -04001314 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1315 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001316
He Yunchao66a41a22016-12-15 16:45:05 +08001317 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001318 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001319 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320
Geoff Langa15472a2015-08-11 11:48:03 -04001321 for (size_t drawbufferIdx = 0;
1322 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 {
Geoff Langa15472a2015-08-11 11:48:03 -04001324 const FramebufferAttachment *attachment =
1325 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1326 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001328 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329
Geoff Langb2f3d052013-08-13 12:49:27 -04001330 // The GL ES 3.0.2 spec (pg 193) states that:
1331 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001332 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1333 // as well
1334 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1335 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001336 // Changes with EXT_color_buffer_float:
1337 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001338 GLenum readComponentType = readFormat.info->componentType;
1339 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001340 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001341 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001342 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001343 drawComponentType == GL_SIGNED_NORMALIZED);
1344
1345 if (extensions.colorBufferFloat)
1346 {
1347 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1348 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1349
1350 if (readFixedOrFloat != drawFixedOrFloat)
1351 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001352 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1353 BlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001354 return false;
1355 }
1356 }
1357 else if (readFixedPoint != drawFixedPoint)
1358 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001359 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1360 BlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001361 return false;
1362 }
1363
1364 if (readComponentType == GL_UNSIGNED_INT &&
1365 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001367 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1368 BlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001369 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
1371
Jamie Madill6163c752015-12-07 16:32:59 -05001372 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001374 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1375 BlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001376 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 }
1378
Jamie Madilla3944d42016-07-22 22:13:26 -04001379 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001380 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001382 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1383 BlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001384 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 }
Geoff Lange4915782017-04-12 15:19:07 -04001386
1387 if (context->getExtensions().webglCompatibility &&
1388 *readColorBuffer == *attachment)
1389 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001390 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001391 return false;
1392 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 }
1394 }
1395
Jamie Madilla3944d42016-07-22 22:13:26 -04001396 if ((readFormat.info->componentType == GL_INT ||
1397 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1398 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001400 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001401 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 }
He Yunchao66a41a22016-12-15 16:45:05 +08001404 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1405 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1406 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1407 // situation is an application error that would lead to a crash in ANGLE.
1408 else if (drawFramebuffer->hasEnabledDrawBuffer())
1409 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001410 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001411 return false;
1412 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 }
1414
He Yunchaoced53ae2016-11-29 15:00:51 +08001415 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001416 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1417 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001419 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001420 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001421 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001422 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001423 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001424 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001426 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 {
Kenneth Russell69382852017-07-21 16:38:44 -04001428 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001429 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001430 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1431 BlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001432 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001434
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001435 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001437 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1438 BlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001439 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001440 }
Geoff Lange4915782017-04-12 15:19:07 -04001441
1442 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1443 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001444 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001445 return false;
1446 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001447 }
He Yunchao66a41a22016-12-15 16:45:05 +08001448 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1449 else if (drawBuffer)
1450 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001451 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001452 return false;
1453 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
1455 }
1456
Martin Radeva3ed4572017-07-27 18:29:37 +03001457 // ANGLE_multiview, Revision 1:
1458 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001459 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1460 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1461 // views in the current read framebuffer is more than one.
1462 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001463 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001464 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001465 return false;
1466 }
1467 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1468 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001469 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001470 return false;
1471 }
1472
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 return true;
1474}
1475
Jamie Madill4928b7c2017-06-20 12:57:39 -04001476bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001477 GLint x,
1478 GLint y,
1479 GLsizei width,
1480 GLsizei height,
1481 GLenum format,
1482 GLenum type,
1483 GLsizei bufSize,
1484 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001485 GLsizei *columns,
1486 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001487 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001488{
1489 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001490 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001491 return false;
1492 }
1493
Brandon Jonesd1049182018-03-28 10:02:20 -07001494 GLsizei writeLength = 0;
1495 GLsizei writeColumns = 0;
1496 GLsizei writeRows = 0;
1497
1498 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1499 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001500 {
Geoff Langb1196682014-07-23 13:47:29 -04001501 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001502 }
1503
Brandon Jonesd1049182018-03-28 10:02:20 -07001504 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001505 {
Geoff Langb1196682014-07-23 13:47:29 -04001506 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001507 }
1508
Brandon Jonesd1049182018-03-28 10:02:20 -07001509 SetRobustLengthParam(length, writeLength);
1510 SetRobustLengthParam(columns, writeColumns);
1511 SetRobustLengthParam(rows, writeRows);
1512
Jamie Madillc29968b2016-01-20 11:17:23 -05001513 return true;
1514}
1515
1516bool ValidateReadnPixelsEXT(Context *context,
1517 GLint x,
1518 GLint y,
1519 GLsizei width,
1520 GLsizei height,
1521 GLenum format,
1522 GLenum type,
1523 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001524 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001525{
1526 if (bufSize < 0)
1527 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001528 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001529 return false;
1530 }
1531
Geoff Lang62fce5b2016-09-30 10:46:35 -04001532 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001533 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001534}
Jamie Madill26e91952014-03-05 15:01:27 -05001535
Jamie Madill4928b7c2017-06-20 12:57:39 -04001536bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001537 GLint x,
1538 GLint y,
1539 GLsizei width,
1540 GLsizei height,
1541 GLenum format,
1542 GLenum type,
1543 GLsizei bufSize,
1544 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001545 GLsizei *columns,
1546 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001547 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001548{
Brandon Jonesd1049182018-03-28 10:02:20 -07001549 GLsizei writeLength = 0;
1550 GLsizei writeColumns = 0;
1551 GLsizei writeRows = 0;
1552
Geoff Lang62fce5b2016-09-30 10:46:35 -04001553 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001554 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001555 return false;
1556 }
1557
Brandon Jonesd1049182018-03-28 10:02:20 -07001558 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1559 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001560 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001561 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001562 }
1563
Brandon Jonesd1049182018-03-28 10:02:20 -07001564 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001565 {
1566 return false;
1567 }
1568
Brandon Jonesd1049182018-03-28 10:02:20 -07001569 SetRobustLengthParam(length, writeLength);
1570 SetRobustLengthParam(columns, writeColumns);
1571 SetRobustLengthParam(rows, writeRows);
1572
Geoff Lang62fce5b2016-09-30 10:46:35 -04001573 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001574}
1575
Jamie Madill43da7c42018-08-01 11:34:49 -04001576bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001577{
1578 if (!context->getExtensions().occlusionQueryBoolean &&
1579 !context->getExtensions().disjointTimerQuery)
1580 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001582 return false;
1583 }
1584
Olli Etuaho41997e72016-03-10 13:38:39 +02001585 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001586}
1587
Jamie Madill43da7c42018-08-01 11:34:49 -04001588bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001589{
1590 if (!context->getExtensions().occlusionQueryBoolean &&
1591 !context->getExtensions().disjointTimerQuery)
1592 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001593 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001594 return false;
1595 }
1596
Olli Etuaho41997e72016-03-10 13:38:39 +02001597 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001598}
1599
Jamie Madill43da7c42018-08-01 11:34:49 -04001600bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001601{
1602 if (!context->getExtensions().occlusionQueryBoolean &&
1603 !context->getExtensions().disjointTimerQuery)
1604 {
1605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1606 return false;
1607 }
1608
1609 return true;
1610}
1611
Jamie Madill43da7c42018-08-01 11:34:49 -04001612bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001613{
1614 if (!ValidQueryType(context, target))
1615 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001616 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001617 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001618 }
1619
1620 if (id == 0)
1621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001622 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001623 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001624 }
1625
1626 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1627 // of zero, if the active query object name for <target> is non-zero (for the
1628 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1629 // the active query for either target is non-zero), if <id> is the name of an
1630 // existing query object whose type does not match <target>, or if <id> is the
1631 // active query object name for any query type, the error INVALID_OPERATION is
1632 // generated.
1633
1634 // Ensure no other queries are active
1635 // NOTE: If other queries than occlusion are supported, we will need to check
1636 // separately that:
1637 // a) The query ID passed is not the current active query for any target/type
1638 // b) There are no active queries for the requested target (and in the case
1639 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1640 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001641
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001642 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001644 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001645 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001646 }
1647
1648 Query *queryObject = context->getQuery(id, true, target);
1649
1650 // check that name was obtained with glGenQueries
1651 if (!queryObject)
1652 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001654 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001655 }
1656
1657 // check for type mismatch
1658 if (queryObject->getType() != target)
1659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001660 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001661 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001662 }
1663
1664 return true;
1665}
1666
Jamie Madill43da7c42018-08-01 11:34:49 -04001667bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001668{
1669 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001670 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673 return false;
1674 }
1675
1676 return ValidateBeginQueryBase(context, target, id);
1677}
1678
Jamie Madill43da7c42018-08-01 11:34:49 -04001679bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001680{
1681 if (!ValidQueryType(context, target))
1682 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001683 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001684 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001685 }
1686
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001687 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001688
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001689 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001691 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001692 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001693 }
1694
Jamie Madill45c785d2014-05-13 14:09:34 -04001695 return true;
1696}
1697
Jamie Madill43da7c42018-08-01 11:34:49 -04001698bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001699{
1700 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001701 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001703 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001704 return false;
1705 }
1706
1707 return ValidateEndQueryBase(context, target);
1708}
1709
Corentin Wallezad3ae902018-03-09 13:40:42 -05001710bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001711{
1712 if (!context->getExtensions().disjointTimerQuery)
1713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001714 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715 return false;
1716 }
1717
Corentin Wallezad3ae902018-03-09 13:40:42 -05001718 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001719 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 return false;
1722 }
1723
1724 Query *queryObject = context->getQuery(id, true, target);
1725 if (queryObject == nullptr)
1726 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001727 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001728 return false;
1729 }
1730
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001731 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001733 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001734 return false;
1735 }
1736
1737 return true;
1738}
1739
Corentin Wallezad3ae902018-03-09 13:40:42 -05001740bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001741{
Geoff Lang2186c382016-10-14 10:54:54 -04001742 if (numParams)
1743 {
1744 *numParams = 0;
1745 }
1746
Corentin Wallezad3ae902018-03-09 13:40:42 -05001747 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001749 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750 return false;
1751 }
1752
1753 switch (pname)
1754 {
1755 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001756 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001758 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759 return false;
1760 }
1761 break;
1762 case GL_QUERY_COUNTER_BITS_EXT:
1763 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001764 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001766 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767 return false;
1768 }
1769 break;
1770 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001772 return false;
1773 }
1774
Geoff Lang2186c382016-10-14 10:54:54 -04001775 if (numParams)
1776 {
1777 // All queries return only one value
1778 *numParams = 1;
1779 }
1780
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001781 return true;
1782}
1783
Corentin Wallezad3ae902018-03-09 13:40:42 -05001784bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001785{
1786 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001787 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001789 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001790 return false;
1791 }
1792
Geoff Lang2186c382016-10-14 10:54:54 -04001793 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001794}
1795
Geoff Lang2186c382016-10-14 10:54:54 -04001796bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001797 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001798 GLenum pname,
1799 GLsizei bufSize,
1800 GLsizei *length,
1801 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802{
Geoff Lang2186c382016-10-14 10:54:54 -04001803 if (!ValidateRobustEntryPoint(context, bufSize))
1804 {
1805 return false;
1806 }
1807
Brandon Jonesd1049182018-03-28 10:02:20 -07001808 GLsizei numParams = 0;
1809
1810 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001811 {
1812 return false;
1813 }
1814
Brandon Jonesd1049182018-03-28 10:02:20 -07001815 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001816 {
1817 return false;
1818 }
1819
Brandon Jonesd1049182018-03-28 10:02:20 -07001820 SetRobustLengthParam(length, numParams);
1821
Geoff Lang2186c382016-10-14 10:54:54 -04001822 return true;
1823}
1824
1825bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1826{
1827 if (numParams)
1828 {
1829 *numParams = 0;
1830 }
1831
Corentin Wallezad3ae902018-03-09 13:40:42 -05001832 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001833
1834 if (!queryObject)
1835 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001836 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001837 return false;
1838 }
1839
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001840 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001842 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001843 return false;
1844 }
1845
1846 switch (pname)
1847 {
1848 case GL_QUERY_RESULT_EXT:
1849 case GL_QUERY_RESULT_AVAILABLE_EXT:
1850 break;
1851
1852 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001853 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001854 return false;
1855 }
1856
Geoff Lang2186c382016-10-14 10:54:54 -04001857 if (numParams)
1858 {
1859 *numParams = 1;
1860 }
1861
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862 return true;
1863}
1864
1865bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1866{
1867 if (!context->getExtensions().disjointTimerQuery)
1868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001869 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001870 return false;
1871 }
Geoff Lang2186c382016-10-14 10:54:54 -04001872 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1873}
1874
1875bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1876 GLuint id,
1877 GLenum pname,
1878 GLsizei bufSize,
1879 GLsizei *length,
1880 GLint *params)
1881{
1882 if (!context->getExtensions().disjointTimerQuery)
1883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001884 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001885 return false;
1886 }
1887
1888 if (!ValidateRobustEntryPoint(context, bufSize))
1889 {
1890 return false;
1891 }
1892
Brandon Jonesd1049182018-03-28 10:02:20 -07001893 GLsizei numParams = 0;
1894
1895 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001896 {
1897 return false;
1898 }
1899
Brandon Jonesd1049182018-03-28 10:02:20 -07001900 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001901 {
1902 return false;
1903 }
1904
Brandon Jonesd1049182018-03-28 10:02:20 -07001905 SetRobustLengthParam(length, numParams);
1906
Geoff Lang2186c382016-10-14 10:54:54 -04001907 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001908}
1909
1910bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1911{
1912 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001913 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001915 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916 return false;
1917 }
Geoff Lang2186c382016-10-14 10:54:54 -04001918 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1919}
1920
1921bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1922 GLuint id,
1923 GLenum pname,
1924 GLsizei bufSize,
1925 GLsizei *length,
1926 GLuint *params)
1927{
1928 if (!context->getExtensions().disjointTimerQuery &&
1929 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001932 return false;
1933 }
1934
1935 if (!ValidateRobustEntryPoint(context, bufSize))
1936 {
1937 return false;
1938 }
1939
Brandon Jonesd1049182018-03-28 10:02:20 -07001940 GLsizei numParams = 0;
1941
1942 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001943 {
1944 return false;
1945 }
1946
Brandon Jonesd1049182018-03-28 10:02:20 -07001947 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001948 {
1949 return false;
1950 }
1951
Brandon Jonesd1049182018-03-28 10:02:20 -07001952 SetRobustLengthParam(length, numParams);
1953
Geoff Lang2186c382016-10-14 10:54:54 -04001954 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001955}
1956
1957bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1958{
1959 if (!context->getExtensions().disjointTimerQuery)
1960 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001961 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001962 return false;
1963 }
Geoff Lang2186c382016-10-14 10:54:54 -04001964 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1965}
1966
1967bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1968 GLuint id,
1969 GLenum pname,
1970 GLsizei bufSize,
1971 GLsizei *length,
1972 GLint64 *params)
1973{
1974 if (!context->getExtensions().disjointTimerQuery)
1975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001977 return false;
1978 }
1979
1980 if (!ValidateRobustEntryPoint(context, bufSize))
1981 {
1982 return false;
1983 }
1984
Brandon Jonesd1049182018-03-28 10:02:20 -07001985 GLsizei numParams = 0;
1986
1987 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001988 {
1989 return false;
1990 }
1991
Brandon Jonesd1049182018-03-28 10:02:20 -07001992 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001993 {
1994 return false;
1995 }
1996
Brandon Jonesd1049182018-03-28 10:02:20 -07001997 SetRobustLengthParam(length, numParams);
1998
Geoff Lang2186c382016-10-14 10:54:54 -04001999 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002000}
2001
2002bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2003{
2004 if (!context->getExtensions().disjointTimerQuery)
2005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002007 return false;
2008 }
Geoff Lang2186c382016-10-14 10:54:54 -04002009 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2010}
2011
2012bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2013 GLuint id,
2014 GLenum pname,
2015 GLsizei bufSize,
2016 GLsizei *length,
2017 GLuint64 *params)
2018{
2019 if (!context->getExtensions().disjointTimerQuery)
2020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002021 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002022 return false;
2023 }
2024
2025 if (!ValidateRobustEntryPoint(context, bufSize))
2026 {
2027 return false;
2028 }
2029
Brandon Jonesd1049182018-03-28 10:02:20 -07002030 GLsizei numParams = 0;
2031
2032 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002033 {
2034 return false;
2035 }
2036
Brandon Jonesd1049182018-03-28 10:02:20 -07002037 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002038 {
2039 return false;
2040 }
2041
Brandon Jonesd1049182018-03-28 10:02:20 -07002042 SetRobustLengthParam(length, numParams);
2043
Geoff Lang2186c382016-10-14 10:54:54 -04002044 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002045}
2046
Jamie Madill5b772312018-03-08 20:28:32 -05002047bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002048 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002049 GLint location,
2050 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002051 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002052{
Jiajia Qin5451d532017-11-16 17:16:34 +08002053 // TODO(Jiajia): Add image uniform check in future.
2054 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002055 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002056 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002057 return false;
2058 }
2059
Jiajia Qin5451d532017-11-16 17:16:34 +08002060 if (!program)
2061 {
2062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2063 return false;
2064 }
2065
2066 if (!program->isLinked())
2067 {
2068 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2069 return false;
2070 }
2071
2072 if (location == -1)
2073 {
2074 // Silently ignore the uniform command
2075 return false;
2076 }
2077
2078 const auto &uniformLocations = program->getUniformLocations();
2079 size_t castedLocation = static_cast<size_t>(location);
2080 if (castedLocation >= uniformLocations.size())
2081 {
2082 context->handleError(InvalidOperation() << "Invalid uniform location");
2083 return false;
2084 }
2085
2086 const auto &uniformLocation = uniformLocations[castedLocation];
2087 if (uniformLocation.ignored)
2088 {
2089 // Silently ignore the uniform command
2090 return false;
2091 }
2092
2093 if (!uniformLocation.used())
2094 {
2095 context->handleError(InvalidOperation());
2096 return false;
2097 }
2098
2099 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2100
2101 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002102 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002103 {
2104 context->handleError(InvalidOperation());
2105 return false;
2106 }
2107
2108 *uniformOut = &uniform;
2109 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002110}
2111
Jamie Madill5b772312018-03-08 20:28:32 -05002112bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002113 GLenum uniformType,
2114 GLsizei count,
2115 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002116{
Jiajia Qin5451d532017-11-16 17:16:34 +08002117 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2118 // It is compatible with INT or BOOL.
2119 // Do these cheap tests first, for a little extra speed.
2120 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002121 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002122 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002123 }
2124
Jiajia Qin5451d532017-11-16 17:16:34 +08002125 if (IsSamplerType(uniformType))
2126 {
2127 // Check that the values are in range.
2128 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2129 for (GLsizei i = 0; i < count; ++i)
2130 {
2131 if (value[i] < 0 || value[i] >= max)
2132 {
2133 context->handleError(InvalidValue() << "sampler uniform value out of range");
2134 return false;
2135 }
2136 }
2137 return true;
2138 }
2139
2140 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2141 return false;
2142}
2143
Jamie Madill5b772312018-03-08 20:28:32 -05002144bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002145{
2146 // Check that the value type is compatible with uniform type.
2147 if (valueType == uniformType)
2148 {
2149 return true;
2150 }
2151
2152 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2153 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002154}
2155
Jamie Madill5b772312018-03-08 20:28:32 -05002156bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002157{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002158 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002159 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002160 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2161 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002162}
2163
Jamie Madill5b772312018-03-08 20:28:32 -05002164bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002165{
2166 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002167 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmana98a6472017-02-02 21:38:32 -05002168 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2169 ValidateUniform1ivValue(context, uniform->type, count, value);
2170}
2171
Jamie Madill5b772312018-03-08 20:28:32 -05002172bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002173 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002174 GLint location,
2175 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002176 GLboolean transpose)
2177{
Geoff Lang92019432017-11-20 13:09:34 -05002178 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002180 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002181 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002182 }
2183
Jamie Madill62d31cb2015-09-11 13:25:51 -04002184 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002185 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002186 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2187 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002188}
2189
Jamie Madill5b772312018-03-08 20:28:32 -05002190bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002191{
2192 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002194 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002195 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002196 }
2197
Jamie Madill0af26e12015-03-05 19:54:33 -05002198 const Caps &caps = context->getCaps();
2199
Jamie Madill893ab082014-05-16 16:56:10 -04002200 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2201 {
2202 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2203
Jamie Madill0af26e12015-03-05 19:54:33 -05002204 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002206 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002207 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002208 }
2209 }
2210
2211 switch (pname)
2212 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002213 case GL_TEXTURE_BINDING_2D:
2214 case GL_TEXTURE_BINDING_CUBE_MAP:
2215 case GL_TEXTURE_BINDING_3D:
2216 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002217 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002218 break;
Olli Etuahod310a432018-08-24 15:40:23 +03002219 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
Olli Etuaho064458a2018-08-30 14:02:02 +03002220 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03002221 {
2222 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
2223 return false;
2224 }
2225 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002226 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2227 if (!context->getExtensions().textureRectangle)
2228 {
2229 context->handleError(InvalidEnum()
2230 << "ANGLE_texture_rectangle extension not present");
2231 return false;
2232 }
2233 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002234 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2235 if (!context->getExtensions().eglStreamConsumerExternal &&
2236 !context->getExtensions().eglImageExternal)
2237 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002238 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2239 "nor GL_OES_EGL_image_external "
2240 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002241 return false;
2242 }
2243 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002244
He Yunchaoced53ae2016-11-29 15:00:51 +08002245 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2246 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002247 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002248 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2249 ASSERT(readFramebuffer);
2250
Jamie Madill427064d2018-04-13 16:20:34 -04002251 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002252 {
Geoff Langb1196682014-07-23 13:47:29 -04002253 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002254 }
2255
Jamie Madille98b1b52018-03-08 09:47:23 -05002256 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002257 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002259 return false;
2260 }
2261
Jamie Madille98b1b52018-03-08 09:47:23 -05002262 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002263 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002265 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002266 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002267 }
2268 }
2269 break;
2270
He Yunchaoced53ae2016-11-29 15:00:51 +08002271 default:
2272 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002273 }
2274
2275 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002276 if (*numParams == 0)
2277 {
2278 return false;
2279 }
2280
2281 return true;
2282}
2283
Brandon Jonesd1049182018-03-28 10:02:20 -07002284bool ValidateGetBooleanvRobustANGLE(Context *context,
2285 GLenum pname,
2286 GLsizei bufSize,
2287 GLsizei *length,
2288 GLboolean *params)
2289{
2290 GLenum nativeType;
2291 unsigned int numParams = 0;
2292
2293 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2294 {
2295 return false;
2296 }
2297
2298 SetRobustLengthParam(length, numParams);
2299
2300 return true;
2301}
2302
2303bool ValidateGetFloatvRobustANGLE(Context *context,
2304 GLenum pname,
2305 GLsizei bufSize,
2306 GLsizei *length,
2307 GLfloat *params)
2308{
2309 GLenum nativeType;
2310 unsigned int numParams = 0;
2311
2312 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2313 {
2314 return false;
2315 }
2316
2317 SetRobustLengthParam(length, numParams);
2318
2319 return true;
2320}
2321
2322bool ValidateGetIntegervRobustANGLE(Context *context,
2323 GLenum pname,
2324 GLsizei bufSize,
2325 GLsizei *length,
2326 GLint *data)
2327{
2328 GLenum nativeType;
2329 unsigned int numParams = 0;
2330
2331 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2332 {
2333 return false;
2334 }
2335
2336 SetRobustLengthParam(length, numParams);
2337
2338 return true;
2339}
2340
2341bool ValidateGetInteger64vRobustANGLE(Context *context,
2342 GLenum pname,
2343 GLsizei bufSize,
2344 GLsizei *length,
2345 GLint64 *data)
2346{
2347 GLenum nativeType;
2348 unsigned int numParams = 0;
2349
2350 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2351 {
2352 return false;
2353 }
2354
2355 if (nativeType == GL_INT_64_ANGLEX)
2356 {
2357 CastStateValues(context, nativeType, pname, numParams, data);
2358 return false;
2359 }
2360
2361 SetRobustLengthParam(length, numParams);
2362 return true;
2363}
2364
Jamie Madill5b772312018-03-08 20:28:32 -05002365bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002366 GLenum pname,
2367 GLsizei bufSize,
2368 GLenum *nativeType,
2369 unsigned int *numParams)
2370{
2371 if (!ValidateRobustEntryPoint(context, bufSize))
2372 {
2373 return false;
2374 }
2375
2376 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2377 {
2378 return false;
2379 }
2380
2381 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002382 {
2383 return false;
2384 }
2385
2386 return true;
2387}
2388
Jamie Madill5b772312018-03-08 20:28:32 -05002389bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002390 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002391 GLint level,
2392 GLenum internalformat,
2393 bool isSubImage,
2394 GLint xoffset,
2395 GLint yoffset,
2396 GLint zoffset,
2397 GLint x,
2398 GLint y,
2399 GLsizei width,
2400 GLsizei height,
2401 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002402 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002403{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002404 TextureType texType = TextureTargetToType(target);
2405
Brandon Jones6cad5662017-06-14 13:25:13 -07002406 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002407 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002408 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2409 return false;
2410 }
2411
2412 if (width < 0 || height < 0)
2413 {
2414 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002415 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002416 }
2417
He Yunchaoced53ae2016-11-29 15:00:51 +08002418 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2419 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002421 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002422 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002423 }
2424
2425 if (border != 0)
2426 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002427 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002428 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002429 }
2430
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002431 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002433 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002434 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002435 }
2436
Jamie Madill43da7c42018-08-01 11:34:49 -04002437 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002438 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002439 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002440 {
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002442 }
2443
Jamie Madille98b1b52018-03-08 09:47:23 -05002444 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002445 {
Geoff Langb1196682014-07-23 13:47:29 -04002446 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002447 }
2448
Martin Radev138064f2016-07-15 12:03:41 +03002449 if (readFramebuffer->getReadBufferState() == GL_NONE)
2450 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002451 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002452 return false;
2453 }
2454
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002455 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2456 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002457 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002458 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002459 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2460 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002461 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002462 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002463 return false;
2464 }
2465
Martin Radev04e2c3b2017-07-27 16:54:35 +03002466 // ANGLE_multiview spec, Revision 1:
2467 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2468 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002469 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2470 // framebuffer is more than one.
2471 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002472 {
2473 context->handleError(InvalidFramebufferOperation()
2474 << "The active read framebuffer object has multiview attachments.");
2475 return false;
2476 }
2477
Jamie Madill43da7c42018-08-01 11:34:49 -04002478 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002479
Geoff Langaae65a42014-05-26 12:43:44 -04002480 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002481 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002482 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002483 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002484 maxDimension = caps.max2DTextureSize;
2485 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002486
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002487 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002488 maxDimension = caps.maxCubeMapTextureSize;
2489 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002490
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002491 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002492 maxDimension = caps.maxRectangleTextureSize;
2493 break;
2494
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002495 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002496 maxDimension = caps.max2DTextureSize;
2497 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002498
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002499 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002500 maxDimension = caps.max3DTextureSize;
2501 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002502
He Yunchaoced53ae2016-11-29 15:00:51 +08002503 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002504 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002506 }
2507
Jamie Madill43da7c42018-08-01 11:34:49 -04002508 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002509 if (!texture)
2510 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002511 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002512 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 }
2514
Geoff Lang69cce582015-09-17 13:20:36 -04002515 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002517 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002518 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002519 }
2520
Jamie Madill43da7c42018-08-01 11:34:49 -04002521 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002522 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002523 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002524
Geoff Lang966c9402017-04-18 12:38:27 -04002525 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002527 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002528 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002529 }
2530
2531 if (isSubImage)
2532 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002533 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2534 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2535 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002537 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002538 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002539 }
2540 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002541 else
2542 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002543 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002544 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002545 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002546 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002547 }
2548
Geoff Langeb66a6e2016-10-31 13:06:12 -04002549 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002550 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002551 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002552 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002553 }
2554
2555 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002556 if (static_cast<int>(width) > maxLevelDimension ||
2557 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002558 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002559 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002560 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002561 }
2562 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002563
Jamie Madill0c8abca2016-07-22 20:21:26 -04002564 if (textureFormatOut)
2565 {
2566 *textureFormatOut = texture->getFormat(target, level);
2567 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002568
2569 // Detect texture copying feedback loops for WebGL.
2570 if (context->getExtensions().webglCompatibility)
2571 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002572 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002573 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002574 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002575 return false;
2576 }
2577 }
2578
Jamie Madill560a8d82014-05-21 13:06:20 -04002579 return true;
2580}
2581
Jamie Madillb42162f2018-08-20 12:58:37 -04002582// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2583// completeness check.
2584const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002585{
2586 const Extensions &extensions = context->getExtensions();
Jamie Madill7f232932018-09-12 11:03:06 -04002587 const State &state = context->getGLState();
Jamie Madille7d80f32018-08-08 15:49:23 -04002588
2589 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2590 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2591 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madilld84b6732018-09-06 15:54:35 -04002592 VertexArray *vertexArray = state.getVertexArray();
2593 ASSERT(vertexArray);
2594
2595 if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
Jamie Madille7d80f32018-08-08 15:49:23 -04002596 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002597 return kErrorBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002598 }
2599
2600 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2601 // Section 6.10 of the WebGL 1.0 spec.
2602 Framebuffer *framebuffer = state.getDrawFramebuffer();
Jamie Madilld84b6732018-09-06 15:54:35 -04002603 ASSERT(framebuffer);
2604
Jamie Madille7d80f32018-08-08 15:49:23 -04002605 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2606 {
2607 ASSERT(framebuffer);
2608 const FramebufferAttachment *dsAttachment =
2609 framebuffer->getStencilOrDepthStencilAttachment();
2610 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2611 ASSERT(stencilBits <= 8);
2612
2613 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2614 if (depthStencilState.stencilTest && stencilBits > 0)
2615 {
2616 GLuint maxStencilValue = (1 << stencilBits) - 1;
2617
2618 bool differentRefs =
2619 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2620 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2621 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2622 (depthStencilState.stencilBackWritemask & maxStencilValue);
2623 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2624 (depthStencilState.stencilBackMask & maxStencilValue);
2625
2626 if (differentRefs || differentWritemasks || differentMasks)
2627 {
2628 if (!extensions.webglCompatibility)
2629 {
2630 WARN() << "This ANGLE implementation does not support separate front/back "
2631 "stencil writemasks, reference values, or stencil mask values.";
2632 }
Jamie Madillb42162f2018-08-20 12:58:37 -04002633 return kErrorStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002634 }
2635 }
2636 }
2637
2638 if (!framebuffer->isComplete(context))
2639 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002640 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2641 return kErrorDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002642 }
2643
2644 if (context->getStateCache().hasAnyEnabledClientAttrib())
2645 {
2646 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2647 {
2648 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2649 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2650 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2651 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madillb42162f2018-08-20 12:58:37 -04002652 return kErrorVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002653 }
2654
2655 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2656 {
2657 // This is an application error that would normally result in a crash, but we catch it
2658 // and return an error
Jamie Madillb42162f2018-08-20 12:58:37 -04002659 return kErrorVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002660 }
2661 }
2662
2663 // If we are running GLES1, there is no current program.
2664 if (context->getClientVersion() >= Version(2, 0))
2665 {
Jamie Madill785e8a02018-10-04 17:42:00 -04002666 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002667 if (!program)
2668 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002669 return kErrorProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002670 }
2671
2672 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2673 // vertex shader stage or fragment shader stage is a undefined behaviour.
2674 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2675 // produce undefined result.
2676 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2677 !program->hasLinkedShaderStage(ShaderType::Fragment))
2678 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002679 return kErrorNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002680 }
2681
2682 if (!program->validateSamplers(nullptr, context->getCaps()))
2683 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002684 return kErrorTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002685 }
2686
2687 if (extensions.multiview)
2688 {
2689 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2690 const int framebufferNumViews = framebuffer->getNumViews();
2691 if (framebufferNumViews != programNumViews)
2692 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002693 return kErrorMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002694 }
2695
2696 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2697 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2698 framebufferNumViews > 1)
2699 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002700 return kErrorMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002701 }
2702
2703 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2704 state.isQueryActive(QueryType::TimeElapsed))
2705 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002706 return kErrorMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002707 }
2708 }
2709
2710 // Uniform buffer validation
2711 for (unsigned int uniformBlockIndex = 0;
2712 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2713 {
2714 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Jamie Madill7f232932018-09-12 11:03:06 -04002715 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Jamie Madille7d80f32018-08-08 15:49:23 -04002716 const OffsetBindingPointer<Buffer> &uniformBuffer =
2717 state.getIndexedUniformBuffer(blockBinding);
2718
2719 if (uniformBuffer.get() == nullptr)
2720 {
2721 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002722 return kErrorUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002723 }
2724
2725 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2726 if (uniformBufferSize < uniformBlock.dataSize)
2727 {
2728 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002729 return kErrorUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002730 }
2731
2732 if (extensions.webglCompatibility &&
2733 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2734 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002735 return kErrorUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002736 }
2737 }
2738
2739 // Do some additonal WebGL-specific validation
2740 if (extensions.webglCompatibility)
2741 {
2742 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2743 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2744 transformFeedbackObject->buffersBoundForOtherUse())
2745 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002746 return kErrorTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002747 }
2748
2749 // Detect rendering feedback loops for WebGL.
2750 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2751 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002752 return kErrorFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002753 }
2754
2755 // Detect that the vertex shader input types match the attribute types
2756 if (!ValidateVertexShaderAttributeTypeMatch(context))
2757 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002758 return kErrorVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002759 }
2760
2761 // Detect that the color buffer types match the fragment shader output types
2762 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2763 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002764 return kErrorDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002765 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002766
2767 const VertexArray *vao = context->getGLState().getVertexArray();
2768 if (vao->hasTransformFeedbackBindingConflict(context))
2769 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002770 return kErrorVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002771 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002772 }
2773 }
2774
Jamie Madillb42162f2018-08-20 12:58:37 -04002775 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002776}
2777
Jamie Madill16e28fd2018-09-12 11:03:05 -04002778bool ValidateDrawMode(Context *context, PrimitiveMode mode)
Jamie Madill250d33f2014-06-06 17:09:03 -04002779{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002780 const Extensions &extensions = context->getExtensions();
2781
Jamie Madill1aeb1312014-06-20 13:21:25 -04002782 switch (mode)
2783 {
Jamie Madill493f9572018-05-24 19:52:15 -04002784 case PrimitiveMode::Points:
2785 case PrimitiveMode::Lines:
2786 case PrimitiveMode::LineLoop:
2787 case PrimitiveMode::LineStrip:
2788 case PrimitiveMode::Triangles:
2789 case PrimitiveMode::TriangleStrip:
2790 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002791 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002792
Jamie Madill493f9572018-05-24 19:52:15 -04002793 case PrimitiveMode::LinesAdjacency:
2794 case PrimitiveMode::LineStripAdjacency:
2795 case PrimitiveMode::TrianglesAdjacency:
2796 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002797 if (!extensions.geometryShader)
2798 {
2799 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2800 return false;
2801 }
2802 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002803 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002805 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002806 }
2807
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002808 // If we are running GLES1, there is no current program.
2809 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002810 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002811 const State &state = context->getGLState();
2812
Jamie Madill785e8a02018-10-04 17:42:00 -04002813 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002814 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002815
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002816 // Do geometry shader specific validations
2817 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002818 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002819 if (!IsCompatibleDrawModeWithGeometryShader(
2820 mode, program->getGeometryShaderInputPrimitiveType()))
2821 {
2822 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2823 IncompatibleDrawModeAgainstGeometryShader);
2824 return false;
2825 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002826 }
2827 }
2828
Jamie Madill9fdaa492018-02-16 10:52:11 -05002829 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002830}
2831
Jamie Madill16e28fd2018-09-12 11:03:05 -04002832bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
2833{
2834 if (!context->getStateCache().isValidDrawMode(mode))
2835 {
2836 return ValidateDrawMode(context, mode);
2837 }
2838
2839 if (count < 0)
2840 {
2841 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2842 return false;
2843 }
2844
2845 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2846 if (drawStatesError)
2847 {
2848 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2849
2850 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2851 // Incomplete.
2852 GLenum errorCode =
2853 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2854 : GL_INVALID_OPERATION);
2855 context->handleError(Error(errorCode, errorMessage));
2856 return false;
2857 }
2858
2859 return true;
2860}
2861
Jamie Madill5b772312018-03-08 20:28:32 -05002862bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002863 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002864 GLint first,
2865 GLsizei count,
2866 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002867{
Jamie Madillfd716582014-06-06 17:09:04 -04002868 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002869 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002870 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002871 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002872 }
2873
Jamie Madill16e28fd2018-09-12 11:03:05 -04002874 if (count < 0)
2875 {
2876 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2877 return false;
2878 }
2879
Jamie Madill7f232932018-09-12 11:03:06 -04002880 const State &state = context->getGLState();
2881 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002882 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002883 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002884 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002885 if (!ValidateTransformFeedbackPrimitiveMode(context,
2886 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002887 {
James Darpinian30b604d2018-03-12 17:26:57 -07002888 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2889 return false;
2890 }
2891
2892 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2893 {
2894 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2895 return false;
2896 }
Jamie Madillfd716582014-06-06 17:09:04 -04002897 }
2898
Jamie Madill16e28fd2018-09-12 11:03:05 -04002899 if (!context->getStateCache().isValidDrawMode(mode))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002900 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002901 return ValidateDrawMode(context, mode);
2902 }
2903
2904 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2905 if (drawStatesError)
2906 {
2907 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2908
2909 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2910 // Incomplete.
2911 GLenum errorCode =
2912 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2913 : GL_INVALID_OPERATION);
2914 context->handleError(Error(errorCode, errorMessage));
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002915 return false;
2916 }
2917
Corentin Wallez71168a02016-12-19 15:11:18 -08002918 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002919 // - first < 0 has been checked as an error condition.
2920 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002921 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002922 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002923 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002924 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002925 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2926 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2927 {
2928 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2929 return false;
2930 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002931
Jamie Madill2da53562018-08-01 11:34:47 -04002932 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002933 {
2934 return false;
2935 }
Jamie Madillfd716582014-06-06 17:09:04 -04002936 }
2937
2938 return true;
2939}
2940
He Yunchaoced53ae2016-11-29 15:00:51 +08002941bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002942 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002943 GLint first,
2944 GLsizei count,
2945 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002946{
Geoff Lang63c5a592017-09-27 14:08:16 -04002947 if (!context->getExtensions().instancedArrays)
2948 {
2949 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2950 return false;
2951 }
2952
Corentin Wallez170efbf2017-05-02 13:45:01 -04002953 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002954 {
2955 return false;
2956 }
2957
Corentin Wallez0dc97812017-06-22 14:38:44 -04002958 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002959}
2960
Jamie Madill493f9572018-05-24 19:52:15 -04002961bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002962{
Jamie Madill250d33f2014-06-06 17:09:03 -04002963 switch (type)
2964 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002965 case GL_UNSIGNED_BYTE:
2966 case GL_UNSIGNED_SHORT:
2967 break;
2968 case GL_UNSIGNED_INT:
2969 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2970 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002971 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002972 return false;
2973 }
2974 break;
2975 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002976 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002977 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002978 }
2979
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002980 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002981
Jamie Madill43da7c42018-08-01 11:34:49 -04002982 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002983 if (curTransformFeedback && curTransformFeedback->isActive() &&
2984 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002985 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002986 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2987 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2988 if (context->getExtensions().geometryShader)
2989 {
2990 if (!ValidateTransformFeedbackPrimitiveMode(
2991 context, curTransformFeedback->getPrimitiveMode(), mode))
2992 {
2993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2994 return false;
2995 }
2996 }
2997 else
2998 {
2999 // It is an invalid operation to call DrawElements, DrawRangeElements or
3000 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
3001 // 86)
3002 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3003 UnsupportedDrawModeForTransformFeedback);
3004 return false;
3005 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003006 }
3007
Jiajia Qind9671222016-11-29 16:30:31 +08003008 return true;
3009}
3010
Jamie Madill5b772312018-03-08 20:28:32 -05003011bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003012 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003013 GLsizei count,
3014 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003015 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003016 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003017{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003018 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003019 return false;
3020
3021 const State &state = context->getGLState();
3022
Corentin Wallez170efbf2017-05-02 13:45:01 -04003023 if (!ValidateDrawBase(context, mode, count))
3024 {
3025 return false;
3026 }
3027
Jamie Madill43da7c42018-08-01 11:34:49 -04003028 const VertexArray *vao = state.getVertexArray();
Jamie Madillcd0a0a32018-10-18 18:41:57 -04003029 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003030
Jamie Madill43da7c42018-08-01 11:34:49 -04003031 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003032
3033 if (context->getExtensions().webglCompatibility)
3034 {
3035 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3036 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3037 {
3038 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3039 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3040 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003041 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003042 return false;
3043 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003044
3045 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3046 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3047 // error is generated.
3048 if (reinterpret_cast<intptr_t>(indices) < 0)
3049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003050 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003051 return false;
3052 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003053 }
Jamie Madillcc73f242018-08-01 11:34:48 -04003054 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
3055 {
3056 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3057 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3058 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3059 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3060 return false;
3061 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003062
3063 if (context->getExtensions().webglCompatibility ||
3064 !context->getGLState().areClientArraysEnabled())
3065 {
Brandon Jones2a018152018-06-08 15:59:26 -07003066 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003067 {
3068 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003069 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3070 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003072 return false;
3073 }
3074 }
3075
Jamie Madill9fdaa492018-02-16 10:52:11 -05003076 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003077 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003078 // This is an application error that would normally result in a crash, but we catch it and
3079 // return an error
3080 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3081 return false;
3082 }
3083
3084 if (count > 0 && elementArrayBuffer)
3085 {
3086 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3087 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3088 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3089 constexpr uint64_t kMaxTypeSize = 8;
3090 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3091 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3092 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3093
3094 uint64_t typeSize = typeBytes;
3095 uint64_t elementCount = static_cast<uint64_t>(count);
3096 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3097
3098 // Doing the multiplication here is overflow-safe
3099 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3100
3101 // The offset can be any value, check for overflows
3102 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3103 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003104 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3106 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003107 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003108
3109 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3110 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003111 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3113 return false;
3114 }
3115
3116 ASSERT(isPow2(typeSize) && typeSize > 0);
3117 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3118 {
3119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003120 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003121 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003122
3123 if (context->getExtensions().webglCompatibility &&
3124 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3125 {
3126 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3127 ElementArrayBufferBoundForTransformFeedback);
3128 return false;
3129 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003130 }
3131
Jamie Madill2da53562018-08-01 11:34:47 -04003132 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003133 {
3134 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madillc1fd7372018-10-26 22:48:39 -04003135 IndexRange indexRange;
3136 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003137
3138 // If we use an index greater than our maximum supported index range, return an error.
3139 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3140 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003141 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003142 {
3143 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3144 return false;
3145 }
3146
Jamie Madill2da53562018-08-01 11:34:47 -04003147 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003148 {
3149 return false;
3150 }
3151
3152 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003153 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003154 }
3155
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003156 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003157}
3158
Jamie Madill5b772312018-03-08 20:28:32 -05003159bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003160 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003161 GLsizei count,
3162 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003163 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003164 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003165{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003166 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003167}
3168
Geoff Lang3edfe032015-09-04 16:38:24 -04003169bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003170 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003171 GLsizei count,
3172 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003173 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003174 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003175{
Geoff Lang63c5a592017-09-27 14:08:16 -04003176 if (!context->getExtensions().instancedArrays)
3177 {
3178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3179 return false;
3180 }
3181
Corentin Wallez170efbf2017-05-02 13:45:01 -04003182 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003183 {
3184 return false;
3185 }
3186
Corentin Wallez0dc97812017-06-22 14:38:44 -04003187 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003188}
3189
He Yunchaoced53ae2016-11-29 15:00:51 +08003190bool ValidateFramebufferTextureBase(Context *context,
3191 GLenum target,
3192 GLenum attachment,
3193 GLuint texture,
3194 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003195{
Geoff Lange8afa902017-09-27 15:00:43 -04003196 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003197 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003198 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003199 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003200 }
3201
3202 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003203 {
3204 return false;
3205 }
3206
Jamie Madill55ec3b12014-07-03 10:38:57 -04003207 if (texture != 0)
3208 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003209 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003210
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003211 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003213 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003214 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003215 }
3216
3217 if (level < 0)
3218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003219 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003220 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003221 }
3222 }
3223
Jamie Madill43da7c42018-08-01 11:34:49 -04003224 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003225 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003226
Jamie Madill84115c92015-04-23 15:00:07 -04003227 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003228 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003229 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003230 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003231 }
3232
3233 return true;
3234}
3235
Geoff Langb1196682014-07-23 13:47:29 -04003236bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003237{
3238 if (program == 0)
3239 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003240 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003241 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003242 }
3243
Jamie Madill43da7c42018-08-01 11:34:49 -04003244 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003245 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003246 {
3247 return false;
3248 }
3249
Jamie Madill0063c512014-08-25 15:47:53 -04003250 if (!programObject || !programObject->isLinked())
3251 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003252 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003253 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003254 }
3255
Geoff Lang7dd2e102014-11-10 15:19:26 -05003256 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003258 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003259 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003260 }
3261
Jamie Madill0063c512014-08-25 15:47:53 -04003262 return true;
3263}
3264
Geoff Langf41d0ee2016-10-07 13:04:23 -04003265static bool ValidateSizedGetUniform(Context *context,
3266 GLuint program,
3267 GLint location,
3268 GLsizei bufSize,
3269 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003270{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003271 if (length)
3272 {
3273 *length = 0;
3274 }
3275
Jamie Madill78f41802014-08-25 15:47:55 -04003276 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003277 {
Jamie Madill78f41802014-08-25 15:47:55 -04003278 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003279 }
3280
Geoff Langf41d0ee2016-10-07 13:04:23 -04003281 if (bufSize < 0)
3282 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003283 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003284 return false;
3285 }
3286
Jamie Madill44a6fbf2018-10-02 13:38:56 -04003287 Program *programObject = context->getProgramResolveLink(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003288 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003289
Jamie Madill78f41802014-08-25 15:47:55 -04003290 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003291 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003292 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003293 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003294 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003296 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003297 }
3298
Geoff Langf41d0ee2016-10-07 13:04:23 -04003299 if (length)
3300 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003301 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003302 }
3303
Jamie Madill0063c512014-08-25 15:47:53 -04003304 return true;
3305}
3306
He Yunchaoced53ae2016-11-29 15:00:51 +08003307bool ValidateGetnUniformfvEXT(Context *context,
3308 GLuint program,
3309 GLint location,
3310 GLsizei bufSize,
3311 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003312{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003313 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003314}
3315
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003316bool ValidateGetnUniformfvRobustANGLE(Context *context,
3317 GLuint program,
3318 GLint location,
3319 GLsizei bufSize,
3320 GLsizei *length,
3321 GLfloat *params)
3322{
3323 UNIMPLEMENTED();
3324 return false;
3325}
3326
He Yunchaoced53ae2016-11-29 15:00:51 +08003327bool ValidateGetnUniformivEXT(Context *context,
3328 GLuint program,
3329 GLint location,
3330 GLsizei bufSize,
3331 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003332{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003333 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3334}
3335
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003336bool ValidateGetnUniformivRobustANGLE(Context *context,
3337 GLuint program,
3338 GLint location,
3339 GLsizei bufSize,
3340 GLsizei *length,
3341 GLint *params)
3342{
3343 UNIMPLEMENTED();
3344 return false;
3345}
3346
3347bool ValidateGetnUniformuivRobustANGLE(Context *context,
3348 GLuint program,
3349 GLint location,
3350 GLsizei bufSize,
3351 GLsizei *length,
3352 GLuint *params)
3353{
3354 UNIMPLEMENTED();
3355 return false;
3356}
3357
Geoff Langf41d0ee2016-10-07 13:04:23 -04003358bool ValidateGetUniformfvRobustANGLE(Context *context,
3359 GLuint program,
3360 GLint location,
3361 GLsizei bufSize,
3362 GLsizei *length,
3363 GLfloat *params)
3364{
3365 if (!ValidateRobustEntryPoint(context, bufSize))
3366 {
3367 return false;
3368 }
3369
Brandon Jonesd1049182018-03-28 10:02:20 -07003370 GLsizei writeLength = 0;
3371
Geoff Langf41d0ee2016-10-07 13:04:23 -04003372 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003373 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3374 {
3375 return false;
3376 }
3377
3378 SetRobustLengthParam(length, writeLength);
3379
3380 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003381}
3382
3383bool ValidateGetUniformivRobustANGLE(Context *context,
3384 GLuint program,
3385 GLint location,
3386 GLsizei bufSize,
3387 GLsizei *length,
3388 GLint *params)
3389{
3390 if (!ValidateRobustEntryPoint(context, bufSize))
3391 {
3392 return false;
3393 }
3394
Brandon Jonesd1049182018-03-28 10:02:20 -07003395 GLsizei writeLength = 0;
3396
Geoff Langf41d0ee2016-10-07 13:04:23 -04003397 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003398 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3399 {
3400 return false;
3401 }
3402
3403 SetRobustLengthParam(length, writeLength);
3404
3405 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003406}
3407
3408bool ValidateGetUniformuivRobustANGLE(Context *context,
3409 GLuint program,
3410 GLint location,
3411 GLsizei bufSize,
3412 GLsizei *length,
3413 GLuint *params)
3414{
3415 if (!ValidateRobustEntryPoint(context, bufSize))
3416 {
3417 return false;
3418 }
3419
3420 if (context->getClientMajorVersion() < 3)
3421 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003422 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003423 return false;
3424 }
3425
Brandon Jonesd1049182018-03-28 10:02:20 -07003426 GLsizei writeLength = 0;
3427
Geoff Langf41d0ee2016-10-07 13:04:23 -04003428 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003429 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3430 {
3431 return false;
3432 }
3433
3434 SetRobustLengthParam(length, writeLength);
3435
3436 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003437}
3438
He Yunchaoced53ae2016-11-29 15:00:51 +08003439bool ValidateDiscardFramebufferBase(Context *context,
3440 GLenum target,
3441 GLsizei numAttachments,
3442 const GLenum *attachments,
3443 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003444{
3445 if (numAttachments < 0)
3446 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003447 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003448 return false;
3449 }
3450
3451 for (GLsizei i = 0; i < numAttachments; ++i)
3452 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003453 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003454 {
3455 if (defaultFramebuffer)
3456 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003457 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003458 return false;
3459 }
3460
3461 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003463 context->handleError(InvalidOperation() << "Requested color attachment is "
3464 "greater than the maximum supported "
3465 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003466 return false;
3467 }
3468 }
3469 else
3470 {
3471 switch (attachments[i])
3472 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003473 case GL_DEPTH_ATTACHMENT:
3474 case GL_STENCIL_ATTACHMENT:
3475 case GL_DEPTH_STENCIL_ATTACHMENT:
3476 if (defaultFramebuffer)
3477 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003478 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3479 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003480 return false;
3481 }
3482 break;
3483 case GL_COLOR:
3484 case GL_DEPTH:
3485 case GL_STENCIL:
3486 if (!defaultFramebuffer)
3487 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003488 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3489 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003490 return false;
3491 }
3492 break;
3493 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003494 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003495 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003496 }
3497 }
3498 }
3499
3500 return true;
3501}
3502
Austin Kinross6ee1e782015-05-29 17:05:37 -07003503bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3504{
Jamie Madill007530e2017-12-28 14:27:04 -05003505 if (!context->getExtensions().debugMarker)
3506 {
3507 // The debug marker calls should not set error state
3508 // However, it seems reasonable to set an error state if the extension is not enabled
3509 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3510 return false;
3511 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003512
Jamie Madill007530e2017-12-28 14:27:04 -05003513 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003514 if (length < 0)
3515 {
3516 return false;
3517 }
3518
3519 if (marker == nullptr)
3520 {
3521 return false;
3522 }
3523
3524 return true;
3525}
3526
3527bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3528{
Jamie Madill007530e2017-12-28 14:27:04 -05003529 if (!context->getExtensions().debugMarker)
3530 {
3531 // The debug marker calls should not set error state
3532 // However, it seems reasonable to set an error state if the extension is not enabled
3533 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3534 return false;
3535 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003536
Jamie Madill007530e2017-12-28 14:27:04 -05003537 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003538 if (length < 0)
3539 {
3540 return false;
3541 }
3542
3543 if (length > 0 && marker == nullptr)
3544 {
3545 return false;
3546 }
3547
3548 return true;
3549}
3550
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003551bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003552{
Geoff Langa8406172015-07-21 16:53:39 -04003553 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003555 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003556 return false;
3557 }
3558
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003559 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003560 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003561 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003562 if (!context->getExtensions().eglImage)
3563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003564 context->handleError(InvalidEnum()
3565 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003566 }
3567 break;
3568
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003569 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003570 if (!context->getExtensions().eglImageExternal)
3571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003572 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3573 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003574 }
Geoff Langa8406172015-07-21 16:53:39 -04003575 break;
3576
3577 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003578 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003579 return false;
3580 }
3581
Rafael Cintron05a449a2018-06-20 18:08:04 -07003582 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003583
Jamie Madill61e16b42017-06-19 11:13:23 -04003584 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003585 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003587 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003588 return false;
3589 }
3590
Jamie Madill007530e2017-12-28 14:27:04 -05003591 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003593 context->handleError(InvalidOperation()
3594 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003595 return false;
3596 }
3597
Yuly Novikov2eb54072018-08-22 16:41:26 -04003598 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003600 context->handleError(InvalidOperation()
3601 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003602 return false;
3603 }
3604
Geoff Langdcab33b2015-07-21 13:03:16 -04003605 return true;
3606}
3607
3608bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003609 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003610 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003611{
Geoff Langa8406172015-07-21 16:53:39 -04003612 if (!context->getExtensions().eglImage)
3613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003614 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003615 return false;
3616 }
3617
3618 switch (target)
3619 {
3620 case GL_RENDERBUFFER:
3621 break;
3622
3623 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003624 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003625 return false;
3626 }
3627
Rafael Cintron05a449a2018-06-20 18:08:04 -07003628 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003629
Jamie Madill61e16b42017-06-19 11:13:23 -04003630 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003631 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003633 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003634 return false;
3635 }
3636
Yuly Novikov2eb54072018-08-22 16:41:26 -04003637 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003639 context->handleError(InvalidOperation()
3640 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003641 return false;
3642 }
3643
Geoff Langdcab33b2015-07-21 13:03:16 -04003644 return true;
3645}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003646
3647bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3648{
Geoff Lang36167ab2015-12-07 10:27:14 -05003649 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003650 {
3651 // The default VAO should always exist
3652 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003653 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003654 return false;
3655 }
3656
3657 return true;
3658}
3659
Geoff Langc5629752015-12-07 16:29:04 -05003660bool ValidateProgramBinaryBase(Context *context,
3661 GLuint program,
3662 GLenum binaryFormat,
3663 const void *binary,
3664 GLint length)
3665{
3666 Program *programObject = GetValidProgram(context, program);
3667 if (programObject == nullptr)
3668 {
3669 return false;
3670 }
3671
3672 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3673 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3674 programBinaryFormats.end())
3675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003676 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003677 return false;
3678 }
3679
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003680 if (context->hasActiveTransformFeedback(program))
3681 {
3682 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003683 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3684 "is associated with an active transform "
3685 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003686 return false;
3687 }
3688
Geoff Langc5629752015-12-07 16:29:04 -05003689 return true;
3690}
3691
3692bool ValidateGetProgramBinaryBase(Context *context,
3693 GLuint program,
3694 GLsizei bufSize,
3695 GLsizei *length,
3696 GLenum *binaryFormat,
3697 void *binary)
3698{
3699 Program *programObject = GetValidProgram(context, program);
3700 if (programObject == nullptr)
3701 {
3702 return false;
3703 }
3704
3705 if (!programObject->isLinked())
3706 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003708 return false;
3709 }
3710
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003711 if (context->getCaps().programBinaryFormats.empty())
3712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003713 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003714 return false;
3715 }
3716
Geoff Langc5629752015-12-07 16:29:04 -05003717 return true;
3718}
Jamie Madillc29968b2016-01-20 11:17:23 -05003719
Jamie Madill5b772312018-03-08 20:28:32 -05003720bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003721{
3722 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003723 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003724 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003725 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3726 return false;
3727 }
3728 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3729 {
3730 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003731 return false;
3732 }
3733
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003734 ASSERT(context->getGLState().getDrawFramebuffer());
3735 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003736 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3737
3738 // This should come first before the check for the default frame buffer
3739 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3740 // rather than INVALID_OPERATION
3741 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3742 {
3743 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3744
3745 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003746 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3747 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003748 {
3749 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003750 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3751 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3752 // 3.1 is still a bit ambiguous about the error, but future specs are
3753 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003755 return false;
3756 }
3757 else if (bufs[colorAttachment] >= maxColorAttachment)
3758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003759 context->handleError(InvalidOperation()
3760 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003761 return false;
3762 }
3763 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3764 frameBufferId != 0)
3765 {
3766 // INVALID_OPERATION-GL is bound to buffer and ith argument
3767 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003768 context->handleError(InvalidOperation()
3769 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003770 return false;
3771 }
3772 }
3773
3774 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3775 // and n is not 1 or bufs is bound to value other than BACK and NONE
3776 if (frameBufferId == 0)
3777 {
3778 if (n != 1)
3779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003780 context->handleError(InvalidOperation()
3781 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003782 return false;
3783 }
3784
3785 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003787 context->handleError(
3788 InvalidOperation()
3789 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003790 return false;
3791 }
3792 }
3793
3794 return true;
3795}
3796
Geoff Lang496c02d2016-10-20 11:38:11 -07003797bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003798 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003799 GLenum pname,
3800 GLsizei *length,
3801 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003802{
Geoff Lang496c02d2016-10-20 11:38:11 -07003803 if (length)
3804 {
3805 *length = 0;
3806 }
3807
3808 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3809 {
3810 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003811 InvalidOperation()
3812 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003813 return false;
3814 }
3815
Corentin Walleze4477002017-12-01 14:39:58 -05003816 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003817 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003818 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003819 return false;
3820 }
3821
Geoff Lang496c02d2016-10-20 11:38:11 -07003822 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003823 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003824 case GL_BUFFER_MAP_POINTER:
3825 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003826
Geoff Lang496c02d2016-10-20 11:38:11 -07003827 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003828 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003829 return false;
3830 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003831
3832 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3833 // target bound to zero generate an INVALID_OPERATION error."
3834 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003835 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003837 context->handleError(InvalidOperation()
3838 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003839 return false;
3840 }
3841
Geoff Lang496c02d2016-10-20 11:38:11 -07003842 if (length)
3843 {
3844 *length = 1;
3845 }
3846
Olli Etuaho4f667482016-03-30 15:56:35 +03003847 return true;
3848}
3849
Corentin Wallez336129f2017-10-17 15:55:40 -04003850bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003851{
Corentin Walleze4477002017-12-01 14:39:58 -05003852 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003853 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003854 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003855 return false;
3856 }
3857
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003858 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003859
3860 if (buffer == nullptr || !buffer->isMapped())
3861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003862 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 return false;
3864 }
3865
3866 return true;
3867}
3868
3869bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003870 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003871 GLintptr offset,
3872 GLsizeiptr length,
3873 GLbitfield access)
3874{
Corentin Walleze4477002017-12-01 14:39:58 -05003875 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003876 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003877 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003878 return false;
3879 }
3880
Brandon Jones6cad5662017-06-14 13:25:13 -07003881 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003883 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3884 return false;
3885 }
3886
3887 if (length < 0)
3888 {
3889 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003890 return false;
3891 }
3892
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003893 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003894
3895 if (!buffer)
3896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003897 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003898 return false;
3899 }
3900
3901 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003902 CheckedNumeric<size_t> checkedOffset(offset);
3903 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003904
Jamie Madille2e406c2016-06-02 13:04:10 -04003905 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003906 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003907 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 return false;
3909 }
3910
3911 // Check for invalid bits in the mask
3912 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3913 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3914 GL_MAP_UNSYNCHRONIZED_BIT;
3915
3916 if (access & ~(allAccessBits))
3917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003918 context->handleError(InvalidValue()
3919 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003920 return false;
3921 }
3922
3923 if (length == 0)
3924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003925 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003926 return false;
3927 }
3928
3929 if (buffer->isMapped())
3930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003931 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003932 return false;
3933 }
3934
3935 // Check for invalid bit combinations
3936 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003938 context->handleError(InvalidOperation()
3939 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003940 return false;
3941 }
3942
3943 GLbitfield writeOnlyBits =
3944 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3945
3946 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003948 context->handleError(InvalidOperation()
3949 << "Invalid access bits when mapping buffer for reading: 0x"
3950 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003951 return false;
3952 }
3953
3954 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003956 context->handleError(
3957 InvalidOperation()
3958 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003959 return false;
3960 }
Geoff Lang79f71042017-08-14 16:43:43 -04003961
3962 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003963}
3964
3965bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003966 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003967 GLintptr offset,
3968 GLsizeiptr length)
3969{
Brandon Jones6cad5662017-06-14 13:25:13 -07003970 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003972 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3973 return false;
3974 }
3975
3976 if (length < 0)
3977 {
3978 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003979 return false;
3980 }
3981
Corentin Walleze4477002017-12-01 14:39:58 -05003982 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003983 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003984 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003985 return false;
3986 }
3987
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003988 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003989
3990 if (buffer == nullptr)
3991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003992 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003993 return false;
3994 }
3995
3996 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003998 context->handleError(InvalidOperation()
3999 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004000 return false;
4001 }
4002
4003 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004004 CheckedNumeric<size_t> checkedOffset(offset);
4005 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004006
Jamie Madille2e406c2016-06-02 13:04:10 -04004007 if (!checkedSize.IsValid() ||
4008 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004010 context->handleError(InvalidValue()
4011 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004012 return false;
4013 }
4014
4015 return true;
4016}
4017
Olli Etuaho41997e72016-03-10 13:38:39 +02004018bool ValidateGenOrDelete(Context *context, GLint n)
4019{
4020 if (n < 0)
4021 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004022 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004023 return false;
4024 }
4025 return true;
4026}
4027
Jamie Madill5b772312018-03-08 20:28:32 -05004028bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004029{
4030 if (!context->getExtensions().robustClientMemory)
4031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004032 context->handleError(InvalidOperation()
4033 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004034 return false;
4035 }
4036
4037 if (bufSize < 0)
4038 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004039 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004040 return false;
4041 }
4042
4043 return true;
4044}
4045
Jamie Madill5b772312018-03-08 20:28:32 -05004046bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004047{
4048 if (bufSize < numParams)
4049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004050 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4051 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004052 return false;
4053 }
4054
4055 return true;
4056}
4057
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004058bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004059 GLenum target,
4060 GLenum attachment,
4061 GLenum pname,
4062 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004063{
Geoff Lange8afa902017-09-27 15:00:43 -04004064 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004066 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004067 return false;
4068 }
4069
4070 int clientVersion = context->getClientMajorVersion();
4071
4072 switch (pname)
4073 {
4074 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4075 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4076 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4077 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4078 break;
4079
Martin Radeve5285d22017-07-14 16:23:53 +03004080 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4081 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4082 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4083 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4084 if (clientVersion < 3 || !context->getExtensions().multiview)
4085 {
4086 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4087 return false;
4088 }
4089 break;
4090
Geoff Langff5b2d52016-09-07 11:32:23 -04004091 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4092 if (clientVersion < 3 && !context->getExtensions().sRGB)
4093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004094 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004095 return false;
4096 }
4097 break;
4098
4099 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4100 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4101 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4102 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4103 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4104 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4105 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4106 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4107 if (clientVersion < 3)
4108 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004109 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004110 return false;
4111 }
4112 break;
4113
Jiawei Shaoa8802472018-05-28 11:17:47 +08004114 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4115 if (!context->getExtensions().geometryShader)
4116 {
4117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4118 return false;
4119 }
4120 break;
4121
Geoff Langff5b2d52016-09-07 11:32:23 -04004122 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004123 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004124 return false;
4125 }
4126
4127 // Determine if the attachment is a valid enum
4128 switch (attachment)
4129 {
4130 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004131 case GL_DEPTH:
4132 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004133 if (clientVersion < 3)
4134 {
Geoff Langfa125c92017-10-24 13:01:46 -04004135 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004136 return false;
4137 }
4138 break;
4139
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004140 case GL_DEPTH_STENCIL_ATTACHMENT:
4141 if (clientVersion < 3 && !context->isWebGL1())
4142 {
4143 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4144 return false;
4145 }
4146 break;
4147
Geoff Langfa125c92017-10-24 13:01:46 -04004148 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004149 case GL_DEPTH_ATTACHMENT:
4150 case GL_STENCIL_ATTACHMENT:
4151 break;
4152
4153 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004154 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4155 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004156 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4157 {
Geoff Langfa125c92017-10-24 13:01:46 -04004158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 return false;
4160 }
4161 break;
4162 }
4163
4164 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4165 ASSERT(framebuffer);
4166
4167 if (framebuffer->id() == 0)
4168 {
4169 if (clientVersion < 3)
4170 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004171 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004172 return false;
4173 }
4174
4175 switch (attachment)
4176 {
4177 case GL_BACK:
4178 case GL_DEPTH:
4179 case GL_STENCIL:
4180 break;
4181
4182 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004183 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004184 return false;
4185 }
4186 }
4187 else
4188 {
4189 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4190 {
4191 // Valid attachment query
4192 }
4193 else
4194 {
4195 switch (attachment)
4196 {
4197 case GL_DEPTH_ATTACHMENT:
4198 case GL_STENCIL_ATTACHMENT:
4199 break;
4200
4201 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004202 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004204 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004205 return false;
4206 }
4207 break;
4208
4209 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004210 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004211 return false;
4212 }
4213 }
4214 }
4215
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004216 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004217 if (attachmentObject)
4218 {
4219 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4220 attachmentObject->type() == GL_TEXTURE ||
4221 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4222
4223 switch (pname)
4224 {
4225 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4226 if (attachmentObject->type() != GL_RENDERBUFFER &&
4227 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 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4235 if (attachmentObject->type() != GL_TEXTURE)
4236 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004237 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004238 return false;
4239 }
4240 break;
4241
4242 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4243 if (attachmentObject->type() != GL_TEXTURE)
4244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004245 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004246 return false;
4247 }
4248 break;
4249
4250 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4251 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4252 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004253 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004254 return false;
4255 }
4256 break;
4257
4258 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4259 if (attachmentObject->type() != GL_TEXTURE)
4260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004262 return false;
4263 }
4264 break;
4265
4266 default:
4267 break;
4268 }
4269 }
4270 else
4271 {
4272 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4273 // is NONE, then querying any other pname will generate INVALID_ENUM.
4274
4275 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4276 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4277 // INVALID_OPERATION for all other pnames
4278
4279 switch (pname)
4280 {
4281 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4282 break;
4283
4284 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4285 if (clientVersion < 3)
4286 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004287 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004288 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004289 return false;
4290 }
4291 break;
4292
4293 default:
4294 if (clientVersion < 3)
4295 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004296 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004297 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004298 return false;
4299 }
4300 else
4301 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004302 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004303 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004304 return false;
4305 }
4306 }
4307 }
4308
Martin Radeve5285d22017-07-14 16:23:53 +03004309 if (numParams)
4310 {
4311 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4312 {
4313 // Only when the viewport offsets are queried we can have a varying number of output
4314 // parameters.
4315 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4316 *numParams = numViews * 2;
4317 }
4318 else
4319 {
4320 // For all other queries we can have only one output parameter.
4321 *numParams = 1;
4322 }
4323 }
4324
Geoff Langff5b2d52016-09-07 11:32:23 -04004325 return true;
4326}
4327
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004328bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004329 GLenum target,
4330 GLenum attachment,
4331 GLenum pname,
4332 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004333 GLsizei *length,
4334 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004335{
4336 if (!ValidateRobustEntryPoint(context, bufSize))
4337 {
4338 return false;
4339 }
4340
Brandon Jonesd1049182018-03-28 10:02:20 -07004341 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004342 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004343 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004344 {
4345 return false;
4346 }
4347
Brandon Jonesd1049182018-03-28 10:02:20 -07004348 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004349 {
4350 return false;
4351 }
4352
Brandon Jonesd1049182018-03-28 10:02:20 -07004353 SetRobustLengthParam(length, numParams);
4354
Geoff Langff5b2d52016-09-07 11:32:23 -04004355 return true;
4356}
4357
Jamie Madill5b772312018-03-08 20:28:32 -05004358bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004359 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004360 GLenum pname,
4361 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004362 GLsizei *length,
4363 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004364{
4365 if (!ValidateRobustEntryPoint(context, bufSize))
4366 {
4367 return false;
4368 }
4369
Brandon Jonesd1049182018-03-28 10:02:20 -07004370 GLsizei numParams = 0;
4371
4372 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004373 {
4374 return false;
4375 }
4376
Brandon Jonesd1049182018-03-28 10:02:20 -07004377 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004378 {
4379 return false;
4380 }
4381
Brandon Jonesd1049182018-03-28 10:02:20 -07004382 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004383 return true;
4384}
4385
Jamie Madill5b772312018-03-08 20:28:32 -05004386bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004387 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004388 GLenum pname,
4389 GLsizei bufSize,
4390 GLsizei *length,
4391 GLint64 *params)
4392{
Brandon Jonesd1049182018-03-28 10:02:20 -07004393 GLsizei numParams = 0;
4394
Geoff Langebebe1c2016-10-14 12:01:31 -04004395 if (!ValidateRobustEntryPoint(context, bufSize))
4396 {
4397 return false;
4398 }
4399
Brandon Jonesd1049182018-03-28 10:02:20 -07004400 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004401 {
4402 return false;
4403 }
4404
Brandon Jonesd1049182018-03-28 10:02:20 -07004405 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004406 {
4407 return false;
4408 }
4409
Brandon Jonesd1049182018-03-28 10:02:20 -07004410 SetRobustLengthParam(length, numParams);
4411
Geoff Langff5b2d52016-09-07 11:32:23 -04004412 return true;
4413}
4414
Jamie Madill5b772312018-03-08 20:28:32 -05004415bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004416{
4417 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004418 if (numParams)
4419 {
4420 *numParams = 1;
4421 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004422
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004423 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
4424 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
4425 ? GetValidProgramNoResolve(context, program)
4426 : GetValidProgram(context, program);
Geoff Langff5b2d52016-09-07 11:32:23 -04004427 if (!programObject)
4428 {
4429 return false;
4430 }
4431
4432 switch (pname)
4433 {
4434 case GL_DELETE_STATUS:
4435 case GL_LINK_STATUS:
4436 case GL_VALIDATE_STATUS:
4437 case GL_INFO_LOG_LENGTH:
4438 case GL_ATTACHED_SHADERS:
4439 case GL_ACTIVE_ATTRIBUTES:
4440 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4441 case GL_ACTIVE_UNIFORMS:
4442 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4443 break;
4444
4445 case GL_PROGRAM_BINARY_LENGTH:
4446 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004448 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4449 "requires GL_OES_get_program_binary or "
4450 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004451 return false;
4452 }
4453 break;
4454
4455 case GL_ACTIVE_UNIFORM_BLOCKS:
4456 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4457 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4458 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4459 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4460 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4461 if (context->getClientMajorVersion() < 3)
4462 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004463 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004464 return false;
4465 }
4466 break;
4467
Yunchao He61afff12017-03-14 15:34:03 +08004468 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004469 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004470 if (context->getClientVersion() < Version(3, 1))
4471 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004472 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004473 return false;
4474 }
4475 break;
4476
Jiawei Shao6ae51612018-02-23 14:03:25 +08004477 case GL_COMPUTE_WORK_GROUP_SIZE:
4478 if (context->getClientVersion() < Version(3, 1))
4479 {
4480 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4481 return false;
4482 }
4483
4484 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4485 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4486 // program which has not been linked successfully, or which does not contain objects to
4487 // form a compute shader.
4488 if (!programObject->isLinked())
4489 {
4490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4491 return false;
4492 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004493 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004494 {
4495 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4496 return false;
4497 }
4498 break;
4499
Jiawei Shao447bfac2018-03-14 14:23:40 +08004500 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4501 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4502 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4503 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4504 if (!context->getExtensions().geometryShader)
4505 {
4506 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4507 return false;
4508 }
4509
4510 // [EXT_geometry_shader] Chapter 7.12
4511 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4512 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4513 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4514 // successfully, or which does not contain objects to form a geometry shader.
4515 if (!programObject->isLinked())
4516 {
4517 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4518 return false;
4519 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004520 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004521 {
4522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4523 return false;
4524 }
4525 break;
4526
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004527 case GL_COMPLETION_STATUS_KHR:
4528 if (!context->getExtensions().parallelShaderCompile)
4529 {
4530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
4531 return false;
4532 }
4533 break;
4534
Geoff Langff5b2d52016-09-07 11:32:23 -04004535 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004536 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004537 return false;
4538 }
4539
4540 return true;
4541}
4542
4543bool ValidateGetProgramivRobustANGLE(Context *context,
4544 GLuint program,
4545 GLenum pname,
4546 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004547 GLsizei *length,
4548 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004549{
4550 if (!ValidateRobustEntryPoint(context, bufSize))
4551 {
4552 return false;
4553 }
4554
Brandon Jonesd1049182018-03-28 10:02:20 -07004555 GLsizei numParams = 0;
4556
4557 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004558 {
4559 return false;
4560 }
4561
Brandon Jonesd1049182018-03-28 10:02:20 -07004562 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004563 {
4564 return false;
4565 }
4566
Brandon Jonesd1049182018-03-28 10:02:20 -07004567 SetRobustLengthParam(length, numParams);
4568
Geoff Langff5b2d52016-09-07 11:32:23 -04004569 return true;
4570}
4571
Geoff Lang740d9022016-10-07 11:20:52 -04004572bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4573 GLenum target,
4574 GLenum pname,
4575 GLsizei bufSize,
4576 GLsizei *length,
4577 GLint *params)
4578{
4579 if (!ValidateRobustEntryPoint(context, bufSize))
4580 {
4581 return false;
4582 }
4583
Brandon Jonesd1049182018-03-28 10:02:20 -07004584 GLsizei numParams = 0;
4585
4586 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004587 {
4588 return false;
4589 }
4590
Brandon Jonesd1049182018-03-28 10:02:20 -07004591 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004592 {
4593 return false;
4594 }
4595
Brandon Jonesd1049182018-03-28 10:02:20 -07004596 SetRobustLengthParam(length, numParams);
4597
Geoff Lang740d9022016-10-07 11:20:52 -04004598 return true;
4599}
4600
Geoff Langd7d0ed32016-10-07 11:33:51 -04004601bool ValidateGetShaderivRobustANGLE(Context *context,
4602 GLuint shader,
4603 GLenum pname,
4604 GLsizei bufSize,
4605 GLsizei *length,
4606 GLint *params)
4607{
4608 if (!ValidateRobustEntryPoint(context, bufSize))
4609 {
4610 return false;
4611 }
4612
Brandon Jonesd1049182018-03-28 10:02:20 -07004613 GLsizei numParams = 0;
4614
4615 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004616 {
4617 return false;
4618 }
4619
Brandon Jonesd1049182018-03-28 10:02:20 -07004620 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004621 {
4622 return false;
4623 }
4624
Brandon Jonesd1049182018-03-28 10:02:20 -07004625 SetRobustLengthParam(length, numParams);
4626
Geoff Langd7d0ed32016-10-07 11:33:51 -04004627 return true;
4628}
4629
Geoff Langc1984ed2016-10-07 12:41:00 -04004630bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004631 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004632 GLenum pname,
4633 GLsizei bufSize,
4634 GLsizei *length,
4635 GLfloat *params)
4636{
4637 if (!ValidateRobustEntryPoint(context, bufSize))
4638 {
4639 return false;
4640 }
4641
Brandon Jonesd1049182018-03-28 10:02:20 -07004642 GLsizei numParams = 0;
4643
4644 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004645 {
4646 return false;
4647 }
4648
Brandon Jonesd1049182018-03-28 10:02:20 -07004649 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004650 {
4651 return false;
4652 }
4653
Brandon Jonesd1049182018-03-28 10:02:20 -07004654 SetRobustLengthParam(length, numParams);
4655
Geoff Langc1984ed2016-10-07 12:41:00 -04004656 return true;
4657}
4658
Geoff Langc1984ed2016-10-07 12:41:00 -04004659bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004660 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004661 GLenum pname,
4662 GLsizei bufSize,
4663 GLsizei *length,
4664 GLint *params)
4665{
Brandon Jonesd1049182018-03-28 10:02:20 -07004666
Geoff Langc1984ed2016-10-07 12:41:00 -04004667 if (!ValidateRobustEntryPoint(context, bufSize))
4668 {
4669 return false;
4670 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004671 GLsizei numParams = 0;
4672 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004673 {
4674 return false;
4675 }
4676
Brandon Jonesd1049182018-03-28 10:02:20 -07004677 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004678 {
4679 return false;
4680 }
4681
Brandon Jonesd1049182018-03-28 10:02:20 -07004682 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004683 return true;
4684}
4685
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004686bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4687 TextureType target,
4688 GLenum pname,
4689 GLsizei bufSize,
4690 GLsizei *length,
4691 GLint *params)
4692{
4693 UNIMPLEMENTED();
4694 return false;
4695}
4696
4697bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4698 TextureType target,
4699 GLenum pname,
4700 GLsizei bufSize,
4701 GLsizei *length,
4702 GLuint *params)
4703{
4704 UNIMPLEMENTED();
4705 return false;
4706}
4707
Geoff Langc1984ed2016-10-07 12:41:00 -04004708bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004709 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004710 GLenum pname,
4711 GLsizei bufSize,
4712 const GLfloat *params)
4713{
4714 if (!ValidateRobustEntryPoint(context, bufSize))
4715 {
4716 return false;
4717 }
4718
Till Rathmannb8543632018-10-02 19:46:14 +02004719 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004720}
4721
Geoff Langc1984ed2016-10-07 12:41:00 -04004722bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004723 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004724 GLenum pname,
4725 GLsizei bufSize,
4726 const GLint *params)
4727{
4728 if (!ValidateRobustEntryPoint(context, bufSize))
4729 {
4730 return false;
4731 }
4732
Till Rathmannb8543632018-10-02 19:46:14 +02004733 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004734}
4735
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004736bool ValidateTexParameterIivRobustANGLE(Context *context,
4737 TextureType target,
4738 GLenum pname,
4739 GLsizei bufSize,
4740 const GLint *params)
4741{
4742 UNIMPLEMENTED();
4743 return false;
4744}
4745
4746bool ValidateTexParameterIuivRobustANGLE(Context *context,
4747 TextureType target,
4748 GLenum pname,
4749 GLsizei bufSize,
4750 const GLuint *params)
4751{
4752 UNIMPLEMENTED();
4753 return false;
4754}
4755
Geoff Langc1984ed2016-10-07 12:41:00 -04004756bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4757 GLuint sampler,
4758 GLenum pname,
4759 GLuint bufSize,
4760 GLsizei *length,
4761 GLfloat *params)
4762{
4763 if (!ValidateRobustEntryPoint(context, bufSize))
4764 {
4765 return false;
4766 }
4767
Brandon Jonesd1049182018-03-28 10:02:20 -07004768 GLsizei numParams = 0;
4769
4770 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004771 {
4772 return false;
4773 }
4774
Brandon Jonesd1049182018-03-28 10:02:20 -07004775 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004776 {
4777 return false;
4778 }
4779
Brandon Jonesd1049182018-03-28 10:02:20 -07004780 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004781 return true;
4782}
4783
Geoff Langc1984ed2016-10-07 12:41:00 -04004784bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4785 GLuint sampler,
4786 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004787 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004788 GLsizei *length,
4789 GLint *params)
4790{
4791 if (!ValidateRobustEntryPoint(context, bufSize))
4792 {
4793 return false;
4794 }
4795
Brandon Jonesd1049182018-03-28 10:02:20 -07004796 GLsizei numParams = 0;
4797
4798 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004799 {
4800 return false;
4801 }
4802
Brandon Jonesd1049182018-03-28 10:02:20 -07004803 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004804 {
4805 return false;
4806 }
4807
Brandon Jonesd1049182018-03-28 10:02:20 -07004808 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004809 return true;
4810}
4811
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004812bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4813 GLuint sampler,
4814 GLenum pname,
4815 GLsizei bufSize,
4816 GLsizei *length,
4817 GLint *params)
4818{
4819 UNIMPLEMENTED();
4820 return false;
4821}
4822
4823bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4824 GLuint sampler,
4825 GLenum pname,
4826 GLsizei bufSize,
4827 GLsizei *length,
4828 GLuint *params)
4829{
4830 UNIMPLEMENTED();
4831 return false;
4832}
4833
Geoff Langc1984ed2016-10-07 12:41:00 -04004834bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4835 GLuint sampler,
4836 GLenum pname,
4837 GLsizei bufSize,
4838 const GLfloat *params)
4839{
4840 if (!ValidateRobustEntryPoint(context, bufSize))
4841 {
4842 return false;
4843 }
4844
Till Rathmannb8543632018-10-02 19:46:14 +02004845 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004846}
4847
Geoff Langc1984ed2016-10-07 12:41:00 -04004848bool ValidateSamplerParameterivRobustANGLE(Context *context,
4849 GLuint sampler,
4850 GLenum pname,
4851 GLsizei bufSize,
4852 const GLint *params)
4853{
4854 if (!ValidateRobustEntryPoint(context, bufSize))
4855 {
4856 return false;
4857 }
4858
Till Rathmannb8543632018-10-02 19:46:14 +02004859 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
Geoff Langc1984ed2016-10-07 12:41:00 -04004860}
4861
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004862bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4863 GLuint sampler,
4864 GLenum pname,
4865 GLsizei bufSize,
4866 const GLint *param)
4867{
4868 UNIMPLEMENTED();
4869 return false;
4870}
4871
4872bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4873 GLuint sampler,
4874 GLenum pname,
4875 GLsizei bufSize,
4876 const GLuint *param)
4877{
4878 UNIMPLEMENTED();
4879 return false;
4880}
4881
Geoff Lang0b031062016-10-13 14:30:04 -04004882bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4883 GLuint index,
4884 GLenum pname,
4885 GLsizei bufSize,
4886 GLsizei *length,
4887 GLfloat *params)
4888{
4889 if (!ValidateRobustEntryPoint(context, bufSize))
4890 {
4891 return false;
4892 }
4893
Brandon Jonesd1049182018-03-28 10:02:20 -07004894 GLsizei writeLength = 0;
4895
4896 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004897 {
4898 return false;
4899 }
4900
Brandon Jonesd1049182018-03-28 10:02:20 -07004901 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004902 {
4903 return false;
4904 }
4905
Brandon Jonesd1049182018-03-28 10:02:20 -07004906 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004907 return true;
4908}
4909
Geoff Lang0b031062016-10-13 14:30:04 -04004910bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4911 GLuint index,
4912 GLenum pname,
4913 GLsizei bufSize,
4914 GLsizei *length,
4915 GLint *params)
4916{
4917 if (!ValidateRobustEntryPoint(context, bufSize))
4918 {
4919 return false;
4920 }
4921
Brandon Jonesd1049182018-03-28 10:02:20 -07004922 GLsizei writeLength = 0;
4923
4924 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004925 {
4926 return false;
4927 }
4928
Brandon Jonesd1049182018-03-28 10:02:20 -07004929 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004930 {
4931 return false;
4932 }
4933
Brandon Jonesd1049182018-03-28 10:02:20 -07004934 SetRobustLengthParam(length, writeLength);
4935
Geoff Lang0b031062016-10-13 14:30:04 -04004936 return true;
4937}
4938
Geoff Lang0b031062016-10-13 14:30:04 -04004939bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4940 GLuint index,
4941 GLenum pname,
4942 GLsizei bufSize,
4943 GLsizei *length,
4944 void **pointer)
4945{
4946 if (!ValidateRobustEntryPoint(context, bufSize))
4947 {
4948 return false;
4949 }
4950
Brandon Jonesd1049182018-03-28 10:02:20 -07004951 GLsizei writeLength = 0;
4952
4953 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004954 {
4955 return false;
4956 }
4957
Brandon Jonesd1049182018-03-28 10:02:20 -07004958 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004959 {
4960 return false;
4961 }
4962
Brandon Jonesd1049182018-03-28 10:02:20 -07004963 SetRobustLengthParam(length, writeLength);
4964
Geoff Lang0b031062016-10-13 14:30:04 -04004965 return true;
4966}
4967
Geoff Lang0b031062016-10-13 14:30:04 -04004968bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4969 GLuint index,
4970 GLenum pname,
4971 GLsizei bufSize,
4972 GLsizei *length,
4973 GLint *params)
4974{
4975 if (!ValidateRobustEntryPoint(context, bufSize))
4976 {
4977 return false;
4978 }
4979
Brandon Jonesd1049182018-03-28 10:02:20 -07004980 GLsizei writeLength = 0;
4981
4982 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004983 {
4984 return false;
4985 }
4986
Brandon Jonesd1049182018-03-28 10:02:20 -07004987 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004988 {
4989 return false;
4990 }
4991
Brandon Jonesd1049182018-03-28 10:02:20 -07004992 SetRobustLengthParam(length, writeLength);
4993
Geoff Lang0b031062016-10-13 14:30:04 -04004994 return true;
4995}
4996
Geoff Lang0b031062016-10-13 14:30:04 -04004997bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4998 GLuint index,
4999 GLenum pname,
5000 GLsizei bufSize,
5001 GLsizei *length,
5002 GLuint *params)
5003{
5004 if (!ValidateRobustEntryPoint(context, bufSize))
5005 {
5006 return false;
5007 }
5008
Brandon Jonesd1049182018-03-28 10:02:20 -07005009 GLsizei writeLength = 0;
5010
5011 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005012 {
5013 return false;
5014 }
5015
Brandon Jonesd1049182018-03-28 10:02:20 -07005016 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005017 {
5018 return false;
5019 }
5020
Brandon Jonesd1049182018-03-28 10:02:20 -07005021 SetRobustLengthParam(length, writeLength);
5022
Geoff Lang0b031062016-10-13 14:30:04 -04005023 return true;
5024}
5025
Geoff Lang6899b872016-10-14 11:30:13 -04005026bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5027 GLuint program,
5028 GLuint uniformBlockIndex,
5029 GLenum pname,
5030 GLsizei bufSize,
5031 GLsizei *length,
5032 GLint *params)
5033{
5034 if (!ValidateRobustEntryPoint(context, bufSize))
5035 {
5036 return false;
5037 }
5038
Brandon Jonesd1049182018-03-28 10:02:20 -07005039 GLsizei writeLength = 0;
5040
5041 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5042 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005043 {
5044 return false;
5045 }
5046
Brandon Jonesd1049182018-03-28 10:02:20 -07005047 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005048 {
5049 return false;
5050 }
5051
Brandon Jonesd1049182018-03-28 10:02:20 -07005052 SetRobustLengthParam(length, writeLength);
5053
Geoff Lang6899b872016-10-14 11:30:13 -04005054 return true;
5055}
5056
Brandon Jones416aaf92018-04-10 08:10:16 -07005057bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005058 GLenum target,
5059 GLenum internalformat,
5060 GLenum pname,
5061 GLsizei bufSize,
5062 GLsizei *length,
5063 GLint *params)
5064{
5065 if (!ValidateRobustEntryPoint(context, bufSize))
5066 {
5067 return false;
5068 }
5069
Brandon Jonesd1049182018-03-28 10:02:20 -07005070 GLsizei numParams = 0;
5071
5072 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5073 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005074 {
5075 return false;
5076 }
5077
Brandon Jonesd1049182018-03-28 10:02:20 -07005078 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005079 {
5080 return false;
5081 }
5082
Brandon Jonesd1049182018-03-28 10:02:20 -07005083 SetRobustLengthParam(length, numParams);
5084
Geoff Lang0a9661f2016-10-20 10:59:20 -07005085 return true;
5086}
5087
Jamie Madill5b772312018-03-08 20:28:32 -05005088bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005089 GLuint attribIndex,
5090 GLint size,
5091 GLenum type,
5092 GLboolean pureInteger)
5093{
5094 const Caps &caps = context->getCaps();
5095 if (attribIndex >= caps.maxVertexAttributes)
5096 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005097 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005098 return false;
5099 }
5100
5101 if (size < 1 || size > 4)
5102 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005103 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005104 return false;
Shao80957d92017-02-20 21:25:59 +08005105 }
5106
5107 switch (type)
5108 {
5109 case GL_BYTE:
5110 case GL_UNSIGNED_BYTE:
5111 case GL_SHORT:
5112 case GL_UNSIGNED_SHORT:
5113 break;
5114
5115 case GL_INT:
5116 case GL_UNSIGNED_INT:
5117 if (context->getClientMajorVersion() < 3)
5118 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005119 context->handleError(InvalidEnum()
5120 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005121 return false;
5122 }
5123 break;
5124
5125 case GL_FIXED:
5126 case GL_FLOAT:
5127 if (pureInteger)
5128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005130 return false;
5131 }
5132 break;
5133
5134 case GL_HALF_FLOAT:
5135 if (context->getClientMajorVersion() < 3)
5136 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005137 context->handleError(InvalidEnum()
5138 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005139 return false;
5140 }
5141 if (pureInteger)
5142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005143 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005144 return false;
5145 }
5146 break;
5147
5148 case GL_INT_2_10_10_10_REV:
5149 case GL_UNSIGNED_INT_2_10_10_10_REV:
5150 if (context->getClientMajorVersion() < 3)
5151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005152 context->handleError(InvalidEnum()
5153 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005154 return false;
5155 }
5156 if (pureInteger)
5157 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005159 return false;
5160 }
5161 if (size != 4)
5162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005163 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5164 "UNSIGNED_INT_2_10_10_10_REV and "
5165 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005166 return false;
5167 }
5168 break;
5169
5170 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005172 return false;
5173 }
5174
5175 return true;
5176}
5177
Geoff Lang76e65652017-03-27 14:58:02 -04005178// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5179// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5180// specified clear value and the type of a buffer that is being cleared generates an
5181// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005182bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005183 GLint drawbuffer,
5184 const GLenum *validComponentTypes,
5185 size_t validComponentTypeCount)
5186{
5187 const FramebufferAttachment *attachment =
5188 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5189 if (attachment)
5190 {
5191 GLenum componentType = attachment->getFormat().info->componentType;
5192 const GLenum *end = validComponentTypes + validComponentTypeCount;
5193 if (std::find(validComponentTypes, end, componentType) == end)
5194 {
5195 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005196 InvalidOperation()
5197 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005198 return false;
5199 }
5200 }
5201
5202 return true;
5203}
5204
Jamie Madill5b772312018-03-08 20:28:32 -05005205bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005206{
5207 if (!ValidateRobustEntryPoint(context, dataSize))
5208 {
5209 return false;
5210 }
5211
Jamie Madill43da7c42018-08-01 11:34:49 -04005212 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005213 if (pixelUnpackBuffer == nullptr)
5214 {
5215 if (dataSize < imageSize)
5216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005217 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005218 }
5219 }
5220 return true;
5221}
5222
Jamie Madill5b772312018-03-08 20:28:32 -05005223bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005224 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005225 GLenum pname,
5226 bool pointerVersion,
5227 GLsizei *numParams)
5228{
5229 if (numParams)
5230 {
5231 *numParams = 0;
5232 }
5233
Corentin Walleze4477002017-12-01 14:39:58 -05005234 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005235 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005236 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005237 return false;
5238 }
5239
5240 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5241 if (!buffer)
5242 {
5243 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 return false;
5246 }
5247
5248 const Extensions &extensions = context->getExtensions();
5249
5250 switch (pname)
5251 {
5252 case GL_BUFFER_USAGE:
5253 case GL_BUFFER_SIZE:
5254 break;
5255
5256 case GL_BUFFER_ACCESS_OES:
5257 if (!extensions.mapBuffer)
5258 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005259 context->handleError(InvalidEnum()
5260 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005261 return false;
5262 }
5263 break;
5264
5265 case GL_BUFFER_MAPPED:
5266 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5267 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5268 !extensions.mapBufferRange)
5269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005270 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5271 "GL_OES_mapbuffer or "
5272 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005273 return false;
5274 }
5275 break;
5276
5277 case GL_BUFFER_MAP_POINTER:
5278 if (!pointerVersion)
5279 {
5280 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005281 InvalidEnum()
5282 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005283 return false;
5284 }
5285 break;
5286
5287 case GL_BUFFER_ACCESS_FLAGS:
5288 case GL_BUFFER_MAP_OFFSET:
5289 case GL_BUFFER_MAP_LENGTH:
5290 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005292 context->handleError(InvalidEnum()
5293 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005294 return false;
5295 }
5296 break;
5297
Geoff Lang79b91402018-10-04 15:11:30 -04005298 case GL_MEMORY_SIZE_ANGLE:
5299 if (!context->getExtensions().memorySize)
5300 {
5301 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
5302 return false;
5303 }
5304 break;
5305
Jamie Madillbe849e42017-05-02 15:49:00 -04005306 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005308 return false;
5309 }
5310
5311 // All buffer parameter queries return one value.
5312 if (numParams)
5313 {
5314 *numParams = 1;
5315 }
5316
5317 return true;
5318}
5319
5320bool ValidateGetRenderbufferParameterivBase(Context *context,
5321 GLenum target,
5322 GLenum pname,
5323 GLsizei *length)
5324{
5325 if (length)
5326 {
5327 *length = 0;
5328 }
5329
5330 if (target != GL_RENDERBUFFER)
5331 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005333 return false;
5334 }
5335
5336 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5337 if (renderbuffer == nullptr)
5338 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005339 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005340 return false;
5341 }
5342
5343 switch (pname)
5344 {
5345 case GL_RENDERBUFFER_WIDTH:
5346 case GL_RENDERBUFFER_HEIGHT:
5347 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5348 case GL_RENDERBUFFER_RED_SIZE:
5349 case GL_RENDERBUFFER_GREEN_SIZE:
5350 case GL_RENDERBUFFER_BLUE_SIZE:
5351 case GL_RENDERBUFFER_ALPHA_SIZE:
5352 case GL_RENDERBUFFER_DEPTH_SIZE:
5353 case GL_RENDERBUFFER_STENCIL_SIZE:
5354 break;
5355
5356 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5357 if (!context->getExtensions().framebufferMultisample)
5358 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005359 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005360 return false;
5361 }
5362 break;
5363
Geoff Lang79b91402018-10-04 15:11:30 -04005364 case GL_MEMORY_SIZE_ANGLE:
5365 if (!context->getExtensions().memorySize)
5366 {
5367 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
5368 return false;
5369 }
5370 break;
5371
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005373 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005374 return false;
5375 }
5376
5377 if (length)
5378 {
5379 *length = 1;
5380 }
5381 return true;
5382}
5383
5384bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5385{
5386 if (length)
5387 {
5388 *length = 0;
5389 }
5390
5391 if (GetValidShader(context, shader) == nullptr)
5392 {
5393 return false;
5394 }
5395
5396 switch (pname)
5397 {
5398 case GL_SHADER_TYPE:
5399 case GL_DELETE_STATUS:
5400 case GL_COMPILE_STATUS:
5401 case GL_INFO_LOG_LENGTH:
5402 case GL_SHADER_SOURCE_LENGTH:
5403 break;
5404
5405 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5406 if (!context->getExtensions().translatedShaderSource)
5407 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005408 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005409 return false;
5410 }
5411 break;
5412
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005413 case GL_COMPLETION_STATUS_KHR:
5414 if (!context->getExtensions().parallelShaderCompile)
5415 {
5416 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
5417 return false;
5418 }
5419 break;
5420
Jamie Madillbe849e42017-05-02 15:49:00 -04005421 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005422 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005423 return false;
5424 }
5425
5426 if (length)
5427 {
5428 *length = 1;
5429 }
5430 return true;
5431}
5432
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005433bool ValidateGetTexParameterBase(Context *context,
5434 TextureType target,
5435 GLenum pname,
5436 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005437{
5438 if (length)
5439 {
5440 *length = 0;
5441 }
5442
5443 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5444 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005445 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 return false;
5447 }
5448
5449 if (context->getTargetTexture(target) == nullptr)
5450 {
5451 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005453 return false;
5454 }
5455
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005456 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5457 {
5458 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5459 return false;
5460 }
5461
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 switch (pname)
5463 {
5464 case GL_TEXTURE_MAG_FILTER:
5465 case GL_TEXTURE_MIN_FILTER:
5466 case GL_TEXTURE_WRAP_S:
5467 case GL_TEXTURE_WRAP_T:
5468 break;
5469
5470 case GL_TEXTURE_USAGE_ANGLE:
5471 if (!context->getExtensions().textureUsage)
5472 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005473 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005474 return false;
5475 }
5476 break;
5477
5478 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005479 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005480 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 return false;
5482 }
5483 break;
5484
5485 case GL_TEXTURE_IMMUTABLE_FORMAT:
5486 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5487 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005488 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005489 return false;
5490 }
5491 break;
5492
5493 case GL_TEXTURE_WRAP_R:
5494 case GL_TEXTURE_IMMUTABLE_LEVELS:
5495 case GL_TEXTURE_SWIZZLE_R:
5496 case GL_TEXTURE_SWIZZLE_G:
5497 case GL_TEXTURE_SWIZZLE_B:
5498 case GL_TEXTURE_SWIZZLE_A:
5499 case GL_TEXTURE_BASE_LEVEL:
5500 case GL_TEXTURE_MAX_LEVEL:
5501 case GL_TEXTURE_MIN_LOD:
5502 case GL_TEXTURE_MAX_LOD:
5503 case GL_TEXTURE_COMPARE_MODE:
5504 case GL_TEXTURE_COMPARE_FUNC:
5505 if (context->getClientMajorVersion() < 3)
5506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005507 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005508 return false;
5509 }
5510 break;
5511
5512 case GL_TEXTURE_SRGB_DECODE_EXT:
5513 if (!context->getExtensions().textureSRGBDecode)
5514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005515 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005516 return false;
5517 }
5518 break;
5519
Yunchao Hebacaa712018-01-30 14:01:39 +08005520 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5521 if (context->getClientVersion() < Version(3, 1))
5522 {
5523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5524 return false;
5525 }
5526 break;
5527
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005528 case GL_GENERATE_MIPMAP:
5529 case GL_TEXTURE_CROP_RECT_OES:
5530 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5531 // after GL_OES_draw_texture functionality implemented
5532 if (context->getClientMajorVersion() > 1)
5533 {
5534 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5535 return false;
5536 }
5537 break;
Geoff Lang79b91402018-10-04 15:11:30 -04005538
5539 case GL_MEMORY_SIZE_ANGLE:
5540 if (!context->getExtensions().memorySize)
5541 {
5542 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
5543 return false;
5544 }
5545 break;
5546
Till Rathmannb8543632018-10-02 19:46:14 +02005547 case GL_TEXTURE_BORDER_COLOR:
5548 if (!context->getExtensions().textureBorderClamp)
5549 {
5550 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
5551 return false;
5552 }
5553 break;
5554
Jamie Madillbe849e42017-05-02 15:49:00 -04005555 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005556 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005557 return false;
5558 }
5559
5560 if (length)
5561 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005562 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005563 }
5564 return true;
5565}
5566
5567bool ValidateGetVertexAttribBase(Context *context,
5568 GLuint index,
5569 GLenum pname,
5570 GLsizei *length,
5571 bool pointer,
5572 bool pureIntegerEntryPoint)
5573{
5574 if (length)
5575 {
5576 *length = 0;
5577 }
5578
5579 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005581 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005582 return false;
5583 }
5584
5585 if (index >= context->getCaps().maxVertexAttributes)
5586 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005587 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005588 return false;
5589 }
5590
5591 if (pointer)
5592 {
5593 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5594 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005595 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005596 return false;
5597 }
5598 }
5599 else
5600 {
5601 switch (pname)
5602 {
5603 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5604 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5605 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5606 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5607 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5608 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5609 case GL_CURRENT_VERTEX_ATTRIB:
5610 break;
5611
5612 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5613 static_assert(
5614 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5615 "ANGLE extension enums not equal to GL enums.");
5616 if (context->getClientMajorVersion() < 3 &&
5617 !context->getExtensions().instancedArrays)
5618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005619 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5620 "requires OpenGL ES 3.0 or "
5621 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005622 return false;
5623 }
5624 break;
5625
5626 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5627 if (context->getClientMajorVersion() < 3)
5628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005629 context->handleError(
5630 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005631 return false;
5632 }
5633 break;
5634
5635 case GL_VERTEX_ATTRIB_BINDING:
5636 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5637 if (context->getClientVersion() < ES_3_1)
5638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005639 context->handleError(InvalidEnum()
5640 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005641 return false;
5642 }
5643 break;
5644
5645 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005646 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005647 return false;
5648 }
5649 }
5650
5651 if (length)
5652 {
5653 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5654 {
5655 *length = 4;
5656 }
5657 else
5658 {
5659 *length = 1;
5660 }
5661 }
5662
5663 return true;
5664}
5665
Jamie Madill4928b7c2017-06-20 12:57:39 -04005666bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005667 GLint x,
5668 GLint y,
5669 GLsizei width,
5670 GLsizei height,
5671 GLenum format,
5672 GLenum type,
5673 GLsizei bufSize,
5674 GLsizei *length,
5675 GLsizei *columns,
5676 GLsizei *rows,
5677 void *pixels)
5678{
5679 if (length != nullptr)
5680 {
5681 *length = 0;
5682 }
5683 if (rows != nullptr)
5684 {
5685 *rows = 0;
5686 }
5687 if (columns != nullptr)
5688 {
5689 *columns = 0;
5690 }
5691
5692 if (width < 0 || height < 0)
5693 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005694 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005695 return false;
5696 }
5697
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005698 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005699
Jamie Madill427064d2018-04-13 16:20:34 -04005700 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005701 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005702 return false;
5703 }
5704
Jamie Madille98b1b52018-03-08 09:47:23 -05005705 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005706 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005707 return false;
5708 }
5709
Jamie Madill690c8eb2018-03-12 15:20:03 -04005710 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005711 ASSERT(framebuffer);
5712
5713 if (framebuffer->getReadBufferState() == GL_NONE)
5714 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005715 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005716 return false;
5717 }
5718
5719 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5720 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5721 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5722 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5723 // situation is an application error that would lead to a crash in ANGLE.
5724 if (readBuffer == nullptr)
5725 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005727 return false;
5728 }
5729
Martin Radev28031682017-07-28 14:47:56 +03005730 // ANGLE_multiview, Revision 1:
5731 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005732 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5733 // in the current read framebuffer is more than one.
5734 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005735 {
5736 context->handleError(InvalidFramebufferOperation()
5737 << "Attempting to read from a multi-view framebuffer.");
5738 return false;
5739 }
5740
Geoff Lang280ba992017-04-18 16:30:58 -04005741 if (context->getExtensions().webglCompatibility)
5742 {
5743 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5744 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5745 // and type before validating the combination of format and type. However, the
5746 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5747 // verifies that GL_INVALID_OPERATION is generated.
5748 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5749 // dEQP/WebGL.
5750 if (!ValidReadPixelsFormatEnum(context, format))
5751 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005753 return false;
5754 }
5755
5756 if (!ValidReadPixelsTypeEnum(context, type))
5757 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005758 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005759 return false;
5760 }
5761 }
5762
Jamie Madill690c8eb2018-03-12 15:20:03 -04005763 GLenum currentFormat = GL_NONE;
5764 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5765
5766 GLenum currentType = GL_NONE;
5767 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5768
Jamie Madillbe849e42017-05-02 15:49:00 -04005769 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5770
5771 bool validFormatTypeCombination =
5772 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5773
5774 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5775 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005776 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005777 return false;
5778 }
5779
5780 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005781 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005782 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5783 {
5784 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005785 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005786 return false;
5787 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005788 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5789 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5790 {
5791 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5792 return false;
5793 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005794
5795 // .. the data would be packed to the buffer object such that the memory writes required
5796 // would exceed the data store size.
5797 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005798 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005799 const auto &pack = context->getGLState().getPackState();
5800
Jamie Madillca2ff382018-07-11 09:01:17 -04005801 GLuint endByte = 0;
5802 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005803 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005804 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005805 return false;
5806 }
5807
Jamie Madillbe849e42017-05-02 15:49:00 -04005808 if (bufSize >= 0)
5809 {
5810 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5811 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005812 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005813 return false;
5814 }
5815 }
5816
5817 if (pixelPackBuffer != nullptr)
5818 {
5819 CheckedNumeric<size_t> checkedEndByte(endByte);
5820 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5821 checkedEndByte += checkedOffset;
5822
5823 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5824 {
5825 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005826 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005827 return false;
5828 }
5829 }
5830
5831 if (pixelPackBuffer == nullptr && length != nullptr)
5832 {
5833 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5834 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005835 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005836 return false;
5837 }
5838
5839 *length = static_cast<GLsizei>(endByte);
5840 }
5841
Geoff Langa953b522018-02-21 16:56:23 -05005842 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005843 angle::CheckedNumeric<int> clippedExtent(length);
5844 if (start < 0)
5845 {
5846 // "subtract" the area that is less than 0
5847 clippedExtent += start;
5848 }
5849
Geoff Langa953b522018-02-21 16:56:23 -05005850 angle::CheckedNumeric<int> readExtent = start;
5851 readExtent += length;
5852 if (!readExtent.IsValid())
5853 {
5854 return false;
5855 }
5856
5857 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005858 {
5859 // Subtract the region to the right of the read buffer
5860 clippedExtent -= (readExtent - bufferSize);
5861 }
5862
5863 if (!clippedExtent.IsValid())
5864 {
Geoff Langa953b522018-02-21 16:56:23 -05005865 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005866 }
5867
Geoff Langa953b522018-02-21 16:56:23 -05005868 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5869 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005870 };
5871
Geoff Langa953b522018-02-21 16:56:23 -05005872 GLsizei writtenColumns = 0;
5873 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5874 {
5875 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5876 return false;
5877 }
5878
5879 GLsizei writtenRows = 0;
5880 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5881 {
5882 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5883 return false;
5884 }
5885
Jamie Madillbe849e42017-05-02 15:49:00 -04005886 if (columns != nullptr)
5887 {
Geoff Langa953b522018-02-21 16:56:23 -05005888 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005889 }
5890
5891 if (rows != nullptr)
5892 {
Geoff Langa953b522018-02-21 16:56:23 -05005893 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005894 }
5895
5896 return true;
5897}
5898
5899template <typename ParamType>
5900bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005901 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005902 GLenum pname,
5903 GLsizei bufSize,
Till Rathmannb8543632018-10-02 19:46:14 +02005904 bool vectorParams,
Jamie Madillbe849e42017-05-02 15:49:00 -04005905 const ParamType *params)
5906{
5907 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5908 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005910 return false;
5911 }
5912
5913 if (context->getTargetTexture(target) == nullptr)
5914 {
5915 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005917 return false;
5918 }
5919
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005920 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005921 if (bufSize >= 0 && bufSize < minBufSize)
5922 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005923 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005924 return false;
5925 }
5926
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005927 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5928 {
5929 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5930 return false;
5931 }
5932
Jamie Madillbe849e42017-05-02 15:49:00 -04005933 switch (pname)
5934 {
5935 case GL_TEXTURE_WRAP_R:
5936 case GL_TEXTURE_SWIZZLE_R:
5937 case GL_TEXTURE_SWIZZLE_G:
5938 case GL_TEXTURE_SWIZZLE_B:
5939 case GL_TEXTURE_SWIZZLE_A:
5940 case GL_TEXTURE_BASE_LEVEL:
5941 case GL_TEXTURE_MAX_LEVEL:
5942 case GL_TEXTURE_COMPARE_MODE:
5943 case GL_TEXTURE_COMPARE_FUNC:
5944 case GL_TEXTURE_MIN_LOD:
5945 case GL_TEXTURE_MAX_LOD:
5946 if (context->getClientMajorVersion() < 3)
5947 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005949 return false;
5950 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005951 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005953 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5954 "available without "
5955 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005956 return false;
5957 }
5958 break;
5959
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005960 case GL_GENERATE_MIPMAP:
5961 case GL_TEXTURE_CROP_RECT_OES:
5962 if (context->getClientMajorVersion() > 1)
5963 {
5964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5965 return false;
5966 }
5967 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005968 default:
5969 break;
5970 }
5971
Olli Etuahod310a432018-08-24 15:40:23 +03005972 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005973 {
5974 switch (pname)
5975 {
5976 case GL_TEXTURE_MIN_FILTER:
5977 case GL_TEXTURE_MAG_FILTER:
5978 case GL_TEXTURE_WRAP_S:
5979 case GL_TEXTURE_WRAP_T:
5980 case GL_TEXTURE_WRAP_R:
5981 case GL_TEXTURE_MIN_LOD:
5982 case GL_TEXTURE_MAX_LOD:
5983 case GL_TEXTURE_COMPARE_MODE:
5984 case GL_TEXTURE_COMPARE_FUNC:
Till Rathmannb8543632018-10-02 19:46:14 +02005985 case GL_TEXTURE_BORDER_COLOR:
JiangYizhou4cff8d62017-07-06 14:54:09 +08005986 context->handleError(InvalidEnum()
5987 << "Invalid parameter for 2D multisampled textures.");
5988 return false;
5989 }
5990 }
5991
Jamie Madillbe849e42017-05-02 15:49:00 -04005992 switch (pname)
5993 {
5994 case GL_TEXTURE_WRAP_S:
5995 case GL_TEXTURE_WRAP_T:
5996 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005997 {
5998 bool restrictedWrapModes =
5999 target == TextureType::External || target == TextureType::Rectangle;
6000 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04006001 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006002 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006003 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006004 }
6005 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006006
6007 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07006008 {
6009 bool restrictedMinFilter =
6010 target == TextureType::External || target == TextureType::Rectangle;
6011 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04006012 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006013 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006014 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006015 }
6016 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006017
6018 case GL_TEXTURE_MAG_FILTER:
6019 if (!ValidateTextureMagFilterValue(context, params))
6020 {
6021 return false;
6022 }
6023 break;
6024
6025 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04006026 if (!context->getExtensions().textureUsage)
6027 {
6028 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6029 return false;
6030 }
6031
Jamie Madillbe849e42017-05-02 15:49:00 -04006032 switch (ConvertToGLenum(params[0]))
6033 {
6034 case GL_NONE:
6035 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
6036 break;
6037
6038 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006039 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006040 return false;
6041 }
6042 break;
6043
6044 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07006045 {
6046 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6047 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04006048 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006049 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006050 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006051 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6052 }
6053 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006054
6055 case GL_TEXTURE_MIN_LOD:
6056 case GL_TEXTURE_MAX_LOD:
6057 // any value is permissible
6058 break;
6059
6060 case GL_TEXTURE_COMPARE_MODE:
6061 if (!ValidateTextureCompareModeValue(context, params))
6062 {
6063 return false;
6064 }
6065 break;
6066
6067 case GL_TEXTURE_COMPARE_FUNC:
6068 if (!ValidateTextureCompareFuncValue(context, params))
6069 {
6070 return false;
6071 }
6072 break;
6073
6074 case GL_TEXTURE_SWIZZLE_R:
6075 case GL_TEXTURE_SWIZZLE_G:
6076 case GL_TEXTURE_SWIZZLE_B:
6077 case GL_TEXTURE_SWIZZLE_A:
6078 switch (ConvertToGLenum(params[0]))
6079 {
6080 case GL_RED:
6081 case GL_GREEN:
6082 case GL_BLUE:
6083 case GL_ALPHA:
6084 case GL_ZERO:
6085 case GL_ONE:
6086 break;
6087
6088 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006089 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006090 return false;
6091 }
6092 break;
6093
6094 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006095 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006097 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006098 return false;
6099 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006100 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006102 context->handleError(InvalidOperation()
6103 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006104 return false;
6105 }
Olli Etuahod310a432018-08-24 15:40:23 +03006106 if ((target == TextureType::_2DMultisample ||
6107 target == TextureType::_2DMultisampleArray) &&
6108 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006109 {
6110 context->handleError(InvalidOperation()
6111 << "Base level must be 0 for multisampled textures.");
6112 return false;
6113 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006114 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006115 {
6116 context->handleError(InvalidOperation()
6117 << "Base level must be 0 for rectangle textures.");
6118 return false;
6119 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006120 break;
6121
6122 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006123 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006124 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006125 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006126 return false;
6127 }
6128 break;
6129
6130 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6131 if (context->getClientVersion() < Version(3, 1))
6132 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006133 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006134 return false;
6135 }
6136 switch (ConvertToGLenum(params[0]))
6137 {
6138 case GL_DEPTH_COMPONENT:
6139 case GL_STENCIL_INDEX:
6140 break;
6141
6142 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006143 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006144 return false;
6145 }
6146 break;
6147
6148 case GL_TEXTURE_SRGB_DECODE_EXT:
6149 if (!ValidateTextureSRGBDecodeValue(context, params))
6150 {
6151 return false;
6152 }
6153 break;
6154
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006155 case GL_GENERATE_MIPMAP:
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006156 if (context->getClientMajorVersion() > 1)
6157 {
6158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6159 return false;
6160 }
6161 break;
Till Rathmannb8543632018-10-02 19:46:14 +02006162
6163 case GL_TEXTURE_CROP_RECT_OES:
6164 if (context->getClientMajorVersion() > 1)
6165 {
6166 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6167 return false;
6168 }
6169 if (!vectorParams)
6170 {
6171 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6172 return false;
6173 }
6174 break;
6175
6176 case GL_TEXTURE_BORDER_COLOR:
6177 if (!context->getExtensions().textureBorderClamp)
6178 {
6179 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
6180 return false;
6181 }
6182 if (!vectorParams)
6183 {
6184 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InsufficientBufferSize);
6185 return false;
6186 }
6187 break;
6188
Jamie Madillbe849e42017-05-02 15:49:00 -04006189 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006190 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006191 return false;
6192 }
6193
6194 return true;
6195}
6196
Till Rathmannb8543632018-10-02 19:46:14 +02006197template bool ValidateTexParameterBase(Context *,
6198 TextureType,
6199 GLenum,
6200 GLsizei,
6201 bool,
6202 const GLfloat *);
6203template bool ValidateTexParameterBase(Context *,
6204 TextureType,
6205 GLenum,
6206 GLsizei,
6207 bool,
6208 const GLint *);
6209template bool ValidateTexParameterBase(Context *,
6210 TextureType,
6211 GLenum,
6212 GLsizei,
6213 bool,
6214 const GLuint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006215
Jamie Madill5b772312018-03-08 20:28:32 -05006216bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006217{
6218 if (index >= MAX_VERTEX_ATTRIBS)
6219 {
6220 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6221 return false;
6222 }
6223
6224 return true;
6225}
6226
6227bool ValidateGetActiveUniformBlockivBase(Context *context,
6228 GLuint program,
6229 GLuint uniformBlockIndex,
6230 GLenum pname,
6231 GLsizei *length)
6232{
6233 if (length)
6234 {
6235 *length = 0;
6236 }
6237
6238 if (context->getClientMajorVersion() < 3)
6239 {
6240 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6241 return false;
6242 }
6243
6244 Program *programObject = GetValidProgram(context, program);
6245 if (!programObject)
6246 {
6247 return false;
6248 }
6249
6250 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6251 {
6252 context->handleError(InvalidValue()
6253 << "uniformBlockIndex exceeds active uniform block count.");
6254 return false;
6255 }
6256
6257 switch (pname)
6258 {
6259 case GL_UNIFORM_BLOCK_BINDING:
6260 case GL_UNIFORM_BLOCK_DATA_SIZE:
6261 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6262 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6263 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6264 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6265 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6266 break;
6267
6268 default:
6269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6270 return false;
6271 }
6272
6273 if (length)
6274 {
6275 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6276 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006277 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006278 programObject->getUniformBlockByIndex(uniformBlockIndex);
6279 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6280 }
6281 else
6282 {
6283 *length = 1;
6284 }
6285 }
6286
6287 return true;
6288}
6289
Jamie Madill9696d072017-08-26 23:19:57 -04006290template <typename ParamType>
6291bool ValidateSamplerParameterBase(Context *context,
6292 GLuint sampler,
6293 GLenum pname,
6294 GLsizei bufSize,
Till Rathmannb8543632018-10-02 19:46:14 +02006295 bool vectorParams,
Jamie Madill9696d072017-08-26 23:19:57 -04006296 ParamType *params)
6297{
6298 if (context->getClientMajorVersion() < 3)
6299 {
6300 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6301 return false;
6302 }
6303
6304 if (!context->isSampler(sampler))
6305 {
6306 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6307 return false;
6308 }
6309
Till Rathmannb8543632018-10-02 19:46:14 +02006310 const GLsizei minBufSize = GetSamplerParameterCount(pname);
Jamie Madill9696d072017-08-26 23:19:57 -04006311 if (bufSize >= 0 && bufSize < minBufSize)
6312 {
6313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6314 return false;
6315 }
6316
6317 switch (pname)
6318 {
6319 case GL_TEXTURE_WRAP_S:
6320 case GL_TEXTURE_WRAP_T:
6321 case GL_TEXTURE_WRAP_R:
6322 if (!ValidateTextureWrapModeValue(context, params, false))
6323 {
6324 return false;
6325 }
6326 break;
6327
6328 case GL_TEXTURE_MIN_FILTER:
6329 if (!ValidateTextureMinFilterValue(context, params, false))
6330 {
6331 return false;
6332 }
6333 break;
6334
6335 case GL_TEXTURE_MAG_FILTER:
6336 if (!ValidateTextureMagFilterValue(context, params))
6337 {
6338 return false;
6339 }
6340 break;
6341
6342 case GL_TEXTURE_MIN_LOD:
6343 case GL_TEXTURE_MAX_LOD:
6344 // any value is permissible
6345 break;
6346
6347 case GL_TEXTURE_COMPARE_MODE:
6348 if (!ValidateTextureCompareModeValue(context, params))
6349 {
6350 return false;
6351 }
6352 break;
6353
6354 case GL_TEXTURE_COMPARE_FUNC:
6355 if (!ValidateTextureCompareFuncValue(context, params))
6356 {
6357 return false;
6358 }
6359 break;
6360
6361 case GL_TEXTURE_SRGB_DECODE_EXT:
6362 if (!ValidateTextureSRGBDecodeValue(context, params))
6363 {
6364 return false;
6365 }
6366 break;
6367
Luc Ferron1b1a8642018-01-23 15:12:01 -05006368 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6369 {
6370 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6371 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6372 {
6373 return false;
6374 }
6375 }
6376 break;
6377
Till Rathmannb8543632018-10-02 19:46:14 +02006378 case GL_TEXTURE_BORDER_COLOR:
6379 if (!context->getExtensions().textureBorderClamp)
6380 {
6381 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
6382 return false;
6383 }
6384 if (!vectorParams)
6385 {
6386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InsufficientBufferSize);
6387 return false;
6388 }
6389 break;
6390
Jamie Madill9696d072017-08-26 23:19:57 -04006391 default:
6392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6393 return false;
6394 }
6395
6396 return true;
6397}
6398
Till Rathmannb8543632018-10-02 19:46:14 +02006399template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, bool, GLfloat *);
6400template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, bool, GLint *);
6401template bool ValidateSamplerParameterBase(Context *,
6402 GLuint,
6403 GLenum,
6404 GLsizei,
6405 bool,
6406 const GLuint *);
Jamie Madill9696d072017-08-26 23:19:57 -04006407
6408bool ValidateGetSamplerParameterBase(Context *context,
6409 GLuint sampler,
6410 GLenum pname,
6411 GLsizei *length)
6412{
6413 if (length)
6414 {
6415 *length = 0;
6416 }
6417
6418 if (context->getClientMajorVersion() < 3)
6419 {
6420 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6421 return false;
6422 }
6423
6424 if (!context->isSampler(sampler))
6425 {
6426 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6427 return false;
6428 }
6429
6430 switch (pname)
6431 {
6432 case GL_TEXTURE_WRAP_S:
6433 case GL_TEXTURE_WRAP_T:
6434 case GL_TEXTURE_WRAP_R:
6435 case GL_TEXTURE_MIN_FILTER:
6436 case GL_TEXTURE_MAG_FILTER:
6437 case GL_TEXTURE_MIN_LOD:
6438 case GL_TEXTURE_MAX_LOD:
6439 case GL_TEXTURE_COMPARE_MODE:
6440 case GL_TEXTURE_COMPARE_FUNC:
6441 break;
6442
Luc Ferron1b1a8642018-01-23 15:12:01 -05006443 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6444 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6445 {
6446 return false;
6447 }
6448 break;
6449
Jamie Madill9696d072017-08-26 23:19:57 -04006450 case GL_TEXTURE_SRGB_DECODE_EXT:
6451 if (!context->getExtensions().textureSRGBDecode)
6452 {
6453 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6454 return false;
6455 }
6456 break;
6457
Till Rathmannb8543632018-10-02 19:46:14 +02006458 case GL_TEXTURE_BORDER_COLOR:
6459 if (!context->getExtensions().textureBorderClamp)
6460 {
6461 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
6462 return false;
6463 }
6464 break;
6465
Jamie Madill9696d072017-08-26 23:19:57 -04006466 default:
6467 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6468 return false;
6469 }
6470
6471 if (length)
6472 {
Till Rathmannb8543632018-10-02 19:46:14 +02006473 *length = GetSamplerParameterCount(pname);
Jamie Madill9696d072017-08-26 23:19:57 -04006474 }
6475 return true;
6476}
6477
6478bool ValidateGetInternalFormativBase(Context *context,
6479 GLenum target,
6480 GLenum internalformat,
6481 GLenum pname,
6482 GLsizei bufSize,
6483 GLsizei *numParams)
6484{
6485 if (numParams)
6486 {
6487 *numParams = 0;
6488 }
6489
6490 if (context->getClientMajorVersion() < 3)
6491 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006492 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006493 return false;
6494 }
6495
6496 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006497 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006498 {
6499 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6500 return false;
6501 }
6502
6503 switch (target)
6504 {
6505 case GL_RENDERBUFFER:
6506 break;
6507
6508 case GL_TEXTURE_2D_MULTISAMPLE:
Yizhou Jiang7818a852018-09-06 15:02:04 +08006509 if (context->getClientVersion() < ES_3_1 &&
6510 !context->getExtensions().textureMultisample)
Jamie Madill9696d072017-08-26 23:19:57 -04006511 {
Yizhou Jiang7818a852018-09-06 15:02:04 +08006512 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
6513 MultisampleTextureExtensionOrES31Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006514 return false;
6515 }
6516 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006517 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6518 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006519 {
6520 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
6521 return false;
6522 }
6523 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006524 default:
6525 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6526 return false;
6527 }
6528
6529 if (bufSize < 0)
6530 {
6531 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6532 return false;
6533 }
6534
6535 GLsizei maxWriteParams = 0;
6536 switch (pname)
6537 {
6538 case GL_NUM_SAMPLE_COUNTS:
6539 maxWriteParams = 1;
6540 break;
6541
6542 case GL_SAMPLES:
6543 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6544 break;
6545
6546 default:
6547 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6548 return false;
6549 }
6550
6551 if (numParams)
6552 {
6553 // glGetInternalFormativ will not overflow bufSize
6554 *numParams = std::min(bufSize, maxWriteParams);
6555 }
6556
6557 return true;
6558}
6559
Jamie Madille98b1b52018-03-08 09:47:23 -05006560bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6561{
Jamie Madill427064d2018-04-13 16:20:34 -04006562 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006563 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03006564 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006565 return false;
6566 }
6567 return true;
6568}
6569
Lingfeng Yang038dd532018-03-29 17:31:52 -07006570bool ValidateMultitextureUnit(Context *context, GLenum texture)
6571{
6572 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6573 {
6574 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6575 return false;
6576 }
6577 return true;
6578}
6579
Olli Etuahod310a432018-08-24 15:40:23 +03006580bool ValidateTexStorageMultisample(Context *context,
6581 TextureType target,
6582 GLsizei samples,
6583 GLint internalFormat,
6584 GLsizei width,
6585 GLsizei height)
6586{
6587 const Caps &caps = context->getCaps();
6588 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6589 static_cast<GLuint>(height) > caps.max2DTextureSize)
6590 {
6591 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureWidthOrHeightOutOfRange);
6592 return false;
6593 }
6594
6595 if (samples == 0)
6596 {
6597 ANGLE_VALIDATION_ERR(context, InvalidValue(), SamplesZero);
6598 return false;
6599 }
6600
6601 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6602 if (!formatCaps.textureAttachment)
6603 {
6604 ANGLE_VALIDATION_ERR(context, InvalidEnum(), RenderableInternalFormat);
6605 return false;
6606 }
6607
6608 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6609 // is one of the unsized base internalformats listed in table 8.11.
6610 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6611 if (formatInfo.internalFormat == GL_NONE)
6612 {
6613 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnsizedInternalFormatUnsupported);
6614 return false;
6615 }
6616
6617 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6618 {
6619 ANGLE_VALIDATION_ERR(context, InvalidOperation(), SamplesOutOfRange);
6620 return false;
6621 }
6622
6623 Texture *texture = context->getTargetTexture(target);
6624 if (!texture || texture->id() == 0)
6625 {
6626 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ZeroBoundToTarget);
6627 return false;
6628 }
6629
6630 if (texture->getImmutableFormat())
6631 {
6632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ImmutableTextureBound);
6633 return false;
6634 }
6635 return true;
6636}
6637
Yizhou Jiang7818a852018-09-06 15:02:04 +08006638bool ValidateTexStorage2DMultisampleBase(Context *context,
6639 TextureType target,
6640 GLsizei samples,
6641 GLint internalFormat,
6642 GLsizei width,
6643 GLsizei height)
6644{
6645 if (target != TextureType::_2DMultisample)
6646 {
6647 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6648 return false;
6649 }
6650
6651 if (width < 1 || height < 1)
6652 {
6653 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
6654 return false;
6655 }
6656
6657 return ValidateTexStorageMultisample(context, target, samples, internalFormat, width, height);
6658}
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08006659
6660bool ValidateGetTexLevelParameterBase(Context *context,
6661 TextureTarget target,
6662 GLint level,
6663 GLenum pname,
6664 GLsizei *length)
6665{
6666
6667 if (length)
6668 {
6669 *length = 0;
6670 }
6671
6672 TextureType type = TextureTargetToType(target);
6673
6674 if (!ValidTexLevelDestinationTarget(context, type))
6675 {
6676 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
6677 return false;
6678 }
6679
6680 if (context->getTargetTexture(type) == nullptr)
6681 {
6682 context->handleError(InvalidEnum() << "No texture bound.");
6683 return false;
6684 }
6685
6686 if (!ValidMipLevel(context, type, level))
6687 {
6688 context->handleError(InvalidValue());
6689 return false;
6690 }
6691
6692 switch (pname)
6693 {
6694 case GL_TEXTURE_RED_TYPE:
6695 case GL_TEXTURE_GREEN_TYPE:
6696 case GL_TEXTURE_BLUE_TYPE:
6697 case GL_TEXTURE_ALPHA_TYPE:
6698 case GL_TEXTURE_DEPTH_TYPE:
6699 break;
6700 case GL_TEXTURE_RED_SIZE:
6701 case GL_TEXTURE_GREEN_SIZE:
6702 case GL_TEXTURE_BLUE_SIZE:
6703 case GL_TEXTURE_ALPHA_SIZE:
6704 case GL_TEXTURE_DEPTH_SIZE:
6705 case GL_TEXTURE_STENCIL_SIZE:
6706 case GL_TEXTURE_SHARED_SIZE:
6707 break;
6708 case GL_TEXTURE_INTERNAL_FORMAT:
6709 case GL_TEXTURE_WIDTH:
6710 case GL_TEXTURE_HEIGHT:
6711 case GL_TEXTURE_DEPTH:
6712 break;
6713 case GL_TEXTURE_SAMPLES:
6714 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
6715 break;
6716 case GL_TEXTURE_COMPRESSED:
6717 break;
6718 default:
6719 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
6720 return false;
6721 }
6722
6723 if (length)
6724 {
6725 *length = 1;
6726 }
6727 return true;
6728}
Jamie Madillc29968b2016-01-20 11:17:23 -05006729} // namespace gl