blob: 37c424dbfc89aa2b289b26f6b4fcc83ee88c692c [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
232 case GL_REPEAT:
233 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400234 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400235 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400236 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700237 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400238 return false;
239 }
240 break;
241
242 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700243 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400244 return false;
245 }
246
247 return true;
248}
249
250template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400251bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400252{
253 switch (ConvertToGLenum(params[0]))
254 {
255 case GL_NEAREST:
256 case GL_LINEAR:
257 break;
258
259 case GL_NEAREST_MIPMAP_NEAREST:
260 case GL_LINEAR_MIPMAP_NEAREST:
261 case GL_NEAREST_MIPMAP_LINEAR:
262 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400263 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400264 {
265 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700266 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400267 return false;
268 }
269 break;
270
271 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700272 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400273 return false;
274 }
275
276 return true;
277}
278
279template <typename ParamType>
280bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
281{
282 switch (ConvertToGLenum(params[0]))
283 {
284 case GL_NEAREST:
285 case GL_LINEAR:
286 break;
287
288 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700289 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400290 return false;
291 }
292
293 return true;
294}
295
296template <typename ParamType>
297bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
298{
299 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
300 switch (ConvertToGLenum(params[0]))
301 {
302 case GL_NONE:
303 case GL_COMPARE_REF_TO_TEXTURE:
304 break;
305
306 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400308 return false;
309 }
310
311 return true;
312}
313
314template <typename ParamType>
315bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
316{
317 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
318 switch (ConvertToGLenum(params[0]))
319 {
320 case GL_LEQUAL:
321 case GL_GEQUAL:
322 case GL_LESS:
323 case GL_GREATER:
324 case GL_EQUAL:
325 case GL_NOTEQUAL:
326 case GL_ALWAYS:
327 case GL_NEVER:
328 break;
329
330 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700331 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400332 return false;
333 }
334
335 return true;
336}
337
338template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700339bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
340{
341 if (!context->getExtensions().textureSRGBDecode)
342 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700344 return false;
345 }
346
347 switch (ConvertToGLenum(params[0]))
348 {
349 case GL_DECODE_EXT:
350 case GL_SKIP_DECODE_EXT:
351 break;
352
353 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700355 return false;
356 }
357
358 return true;
359}
360
Luc Ferron1b1a8642018-01-23 15:12:01 -0500361bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
362{
363 if (!context->getExtensions().textureFilterAnisotropic)
364 {
365 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
366 return false;
367 }
368
369 return true;
370}
371
372bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
373{
374 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
375 {
376 return false;
377 }
378
379 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
380
381 if (paramValue < 1 || paramValue > largest)
382 {
383 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
384 return false;
385 }
386
387 return true;
388}
389
Jamie Madill5b772312018-03-08 20:28:32 -0500390bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400391{
Jamie Madill785e8a02018-10-04 17:42:00 -0400392 const Program *program = context->getGLState().getLinkedProgram(context);
Geoff Lange0cff192017-05-30 13:04:56 -0400393 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
394
Jamie Madille7d80f32018-08-08 15:49:23 -0400395 return ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
396 framebuffer->getDrawBufferTypeMask().to_ulong(),
397 program->getActiveOutputVariables().to_ulong(),
398 framebuffer->getDrawBufferMask().to_ulong());
Geoff Lange0cff192017-05-30 13:04:56 -0400399}
400
Jamie Madill5b772312018-03-08 20:28:32 -0500401bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400402{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700403 const auto &glState = context->getGLState();
Jamie Madill785e8a02018-10-04 17:42:00 -0400404 const Program *program = context->getGLState().getLinkedProgram(context);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400405 const VertexArray *vao = context->getGLState().getVertexArray();
406
Brandon Jonesc405ae72017-12-06 14:15:03 -0800407 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
408 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
409 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
410
411 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
412 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
413 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
414
Jamie Madille7d80f32018-08-08 15:49:23 -0400415 return ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(),
416 vaoAttribTypeBits, program->getAttributesMask().to_ulong(),
417 0xFFFF);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400418}
419
Jamie Madill493f9572018-05-24 19:52:15 -0400420bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
421 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800422{
423 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400424 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800425 {
Jamie Madill493f9572018-05-24 19:52:15 -0400426 case PrimitiveMode::Points:
427 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
428 case PrimitiveMode::Lines:
429 case PrimitiveMode::LineStrip:
430 case PrimitiveMode::LineLoop:
431 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
432 case PrimitiveMode::LinesAdjacency:
433 case PrimitiveMode::LineStripAdjacency:
434 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
435 case PrimitiveMode::Triangles:
436 case PrimitiveMode::TriangleFan:
437 case PrimitiveMode::TriangleStrip:
438 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
439 case PrimitiveMode::TrianglesAdjacency:
440 case PrimitiveMode::TriangleStripAdjacency:
441 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800442 default:
443 UNREACHABLE();
444 return false;
445 }
446}
447
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700448// GLES1 texture parameters are a small subset of the others
449bool IsValidGLES1TextureParameter(GLenum pname)
450{
451 switch (pname)
452 {
453 case GL_TEXTURE_MAG_FILTER:
454 case GL_TEXTURE_MIN_FILTER:
455 case GL_TEXTURE_WRAP_S:
456 case GL_TEXTURE_WRAP_T:
457 case GL_TEXTURE_WRAP_R:
458 case GL_GENERATE_MIPMAP:
459 case GL_TEXTURE_CROP_RECT_OES:
460 return true;
461 default:
462 return false;
463 }
464}
Geoff Langf41a7152016-09-19 15:11:17 -0400465} // anonymous namespace
466
Brandon Jonesd1049182018-03-28 10:02:20 -0700467void SetRobustLengthParam(GLsizei *length, GLsizei value)
468{
469 if (length)
470 {
471 *length = value;
472 }
473}
474
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500475bool IsETC2EACFormat(const GLenum format)
476{
477 // ES 3.1, Table 8.19
478 switch (format)
479 {
480 case GL_COMPRESSED_R11_EAC:
481 case GL_COMPRESSED_SIGNED_R11_EAC:
482 case GL_COMPRESSED_RG11_EAC:
483 case GL_COMPRESSED_SIGNED_RG11_EAC:
484 case GL_COMPRESSED_RGB8_ETC2:
485 case GL_COMPRESSED_SRGB8_ETC2:
486 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
487 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
488 case GL_COMPRESSED_RGBA8_ETC2_EAC:
489 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
490 return true;
491
492 default:
493 return false;
494 }
495}
496
Jamie Madill5b772312018-03-08 20:28:32 -0500497bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400498{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800499 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400500 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800501 case TextureType::_2D:
502 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800503 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400504
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800505 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400506 return context->getExtensions().textureRectangle;
507
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800508 case TextureType::_3D:
509 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800510 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500511
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800512 case TextureType::_2DMultisample:
Yizhou Jiang7818a852018-09-06 15:02:04 +0800513 return (context->getClientVersion() >= Version(3, 1) ||
514 context->getExtensions().textureMultisample);
Olli Etuahod310a432018-08-24 15:40:23 +0300515 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300516 return context->getExtensions().textureStorageMultisample2DArray;
Geoff Lang3b573612016-10-31 14:08:10 -0400517
He Yunchaoced53ae2016-11-29 15:00:51 +0800518 default:
519 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500520 }
Jamie Madill35d15012013-10-07 10:46:37 -0400521}
522
Jamie Madill5b772312018-03-08 20:28:32 -0500523bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500524{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800525 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500526 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800527 case TextureType::_2D:
528 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500529 return true;
530
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800531 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400532 return context->getExtensions().textureRectangle;
533
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500534 default:
535 return false;
536 }
537}
538
Jamie Madill5b772312018-03-08 20:28:32 -0500539bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500540{
541 switch (target)
542 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800543 case TextureType::_3D:
544 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300545 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500546
547 default:
548 return false;
549 }
550}
551
Ian Ewellbda75592016-04-18 17:25:54 -0400552// Most texture GL calls are not compatible with external textures, so we have a separate validation
553// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500554bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400555{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800556 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400557 (context->getExtensions().eglImageExternal ||
558 context->getExtensions().eglStreamConsumerExternal);
559}
560
Shannon Woods4dfed832014-03-17 20:03:39 -0400561// This function differs from ValidTextureTarget in that the target must be
562// usable as the destination of a 2D operation-- so a cube face is valid, but
563// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400564// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500565bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400566{
567 switch (target)
568 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800569 case TextureTarget::_2D:
570 case TextureTarget::CubeMapNegativeX:
571 case TextureTarget::CubeMapNegativeY:
572 case TextureTarget::CubeMapNegativeZ:
573 case TextureTarget::CubeMapPositiveX:
574 case TextureTarget::CubeMapPositiveY:
575 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800576 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800577 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400578 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800579 default:
580 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500581 }
582}
583
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800584bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400585 PrimitiveMode transformFeedbackPrimitiveMode,
586 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800587{
588 ASSERT(context);
589
590 if (!context->getExtensions().geometryShader)
591 {
592 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
593 // that does not match the current transform feedback object's draw mode (if transform
594 // feedback is active), (3.0.2, section 2.14, pg 86)
595 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
596 }
597
598 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400599 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800600 {
Jamie Madill493f9572018-05-24 19:52:15 -0400601 case PrimitiveMode::Points:
602 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
603 case PrimitiveMode::Lines:
604 case PrimitiveMode::LineStrip:
605 case PrimitiveMode::LineLoop:
606 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
607 case PrimitiveMode::Triangles:
608 case PrimitiveMode::TriangleFan:
609 case PrimitiveMode::TriangleStrip:
610 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800611 default:
612 UNREACHABLE();
613 return false;
614 }
615}
616
Jamie Madill5b772312018-03-08 20:28:32 -0500617bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400618 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400619 GLsizei count,
620 GLenum type,
621 const GLvoid *indices,
622 GLsizei primcount)
623{
624 if (primcount < 0)
625 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700626 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400627 return false;
628 }
629
630 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
631 {
632 return false;
633 }
634
Jamie Madill9fdaa492018-02-16 10:52:11 -0500635 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400636}
637
638bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400639 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400640 GLint first,
641 GLsizei count,
642 GLsizei primcount)
643{
644 if (primcount < 0)
645 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700646 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400647 return false;
648 }
649
650 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
651 {
652 return false;
653 }
654
Jamie Madill9fdaa492018-02-16 10:52:11 -0500655 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400656}
657
Jamie Madill5b772312018-03-08 20:28:32 -0500658bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400659{
660 // Verify there is at least one active attribute with a divisor of zero
661 const State &state = context->getGLState();
662
Jamie Madill785e8a02018-10-04 17:42:00 -0400663 Program *program = state.getLinkedProgram(context);
Jamie Madillbe849e42017-05-02 15:49:00 -0400664
665 const auto &attribs = state.getVertexArray()->getVertexAttributes();
666 const auto &bindings = state.getVertexArray()->getVertexBindings();
667 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
668 {
669 const VertexAttribute &attrib = attribs[attributeIndex];
670 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300671 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400672 {
673 return true;
674 }
675 }
676
Brandon Jonesafa75152017-07-21 13:11:29 -0700677 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400678 return false;
679}
680
Jamie Madill5b772312018-03-08 20:28:32 -0500681bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500682{
683 switch (target)
684 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800685 case TextureType::_3D:
686 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800687 return true;
688 default:
689 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400690 }
691}
692
Jamie Madill5b772312018-03-08 20:28:32 -0500693bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800694{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800695 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800696 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800697 case TextureType::_2D:
698 case TextureType::_2DArray:
699 case TextureType::_2DMultisample:
700 case TextureType::CubeMap:
701 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800702 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800703 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400704 return context->getExtensions().textureRectangle;
Olli Etuahod310a432018-08-24 15:40:23 +0300705 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300706 return context->getExtensions().textureStorageMultisample2DArray;
He Yunchao11b038b2016-11-22 21:24:04 +0800707 default:
708 return false;
709 }
710}
711
Jamie Madill5b772312018-03-08 20:28:32 -0500712bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500713{
He Yunchaoced53ae2016-11-29 15:00:51 +0800714 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
715 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400716 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500717
718 switch (target)
719 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800720 case GL_FRAMEBUFFER:
721 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400722
He Yunchaoced53ae2016-11-29 15:00:51 +0800723 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800724 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400725 return (context->getExtensions().framebufferBlit ||
726 context->getClientMajorVersion() >= 3);
727
He Yunchaoced53ae2016-11-29 15:00:51 +0800728 default:
729 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500730 }
731}
732
Jamie Madill5b772312018-03-08 20:28:32 -0500733bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400734{
Jamie Madillc29968b2016-01-20 11:17:23 -0500735 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400736 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800737 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400738 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800739 case TextureType::_2D:
740 case TextureType::_2DArray:
741 case TextureType::_2DMultisample:
Olli Etuahod310a432018-08-24 15:40:23 +0300742 case TextureType::_2DMultisampleArray:
743 // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
744 // level-of-detail" for multisample textures should be. Could maybe make it zero.
Jamie Madillc29968b2016-01-20 11:17:23 -0500745 maxDimension = caps.max2DTextureSize;
746 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800747 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800748 maxDimension = caps.maxCubeMapTextureSize;
749 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800750 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400751 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800752 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800753 maxDimension = caps.max3DTextureSize;
754 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800755 default:
756 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400757 }
758
Jamie Madill43da7c42018-08-01 11:34:49 -0400759 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400760}
761
Jamie Madill5b772312018-03-08 20:28:32 -0500762bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800763 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700764 GLint level,
765 GLsizei width,
766 GLsizei height,
767 GLsizei depth,
768 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400769{
Brandon Jones6cad5662017-06-14 13:25:13 -0700770 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400771 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700772 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400773 return false;
774 }
Austin Kinross08528e12015-10-07 16:24:40 -0700775 // TexSubImage parameters can be NPOT without textureNPOT extension,
776 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500777 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500778 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500779 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400780 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400781 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700782 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400783 return false;
784 }
785
786 if (!ValidMipLevel(context, target, level))
787 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700788 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400789 return false;
790 }
791
792 return true;
793}
794
Geoff Lang966c9402017-04-18 12:38:27 -0400795bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
796{
797 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
798 (size % blockSize == 0);
799}
800
Jamie Madill5b772312018-03-08 20:28:32 -0500801bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500802 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400803 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500804 GLsizei width,
805 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400806{
Jamie Madill43da7c42018-08-01 11:34:49 -0400807 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400808 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400809 {
810 return false;
811 }
812
Geoff Lang966c9402017-04-18 12:38:27 -0400813 if (width < 0 || height < 0)
814 {
815 return false;
816 }
817
818 if (CompressedTextureFormatRequiresExactSize(internalFormat))
819 {
820 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
821 // block size for level 0 but WebGL disallows this.
822 bool smallerThanBlockSizeAllowed =
823 level > 0 || !context->getExtensions().webglCompatibility;
824
825 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
826 smallerThanBlockSizeAllowed) ||
827 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
828 smallerThanBlockSizeAllowed))
829 {
830 return false;
831 }
832 }
833
834 return true;
835}
836
Jamie Madill5b772312018-03-08 20:28:32 -0500837bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400838 GLenum internalFormat,
839 GLint xoffset,
840 GLint yoffset,
841 GLsizei width,
842 GLsizei height,
843 size_t textureWidth,
844 size_t textureHeight)
845{
Jamie Madill43da7c42018-08-01 11:34:49 -0400846 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400847 if (!formatInfo.compressed)
848 {
849 return false;
850 }
851
Geoff Lang44ff5a72017-02-03 15:15:43 -0500852 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400853 {
854 return false;
855 }
856
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500857 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400858 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500859 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400860 yoffset % formatInfo.compressedBlockHeight != 0)
861 {
862 return false;
863 }
864
865 // Allowed to either have data that is a multiple of block size or is smaller than the block
866 // size but fills the entire mip
867 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
868 static_cast<size_t>(width) == textureWidth &&
869 static_cast<size_t>(height) == textureHeight;
870 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
871 (height % formatInfo.compressedBlockHeight) == 0;
872 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400873 {
874 return false;
875 }
876 }
877
Geoff Langd4f180b2013-09-24 13:57:44 -0400878 return true;
879}
880
Jamie Madill5b772312018-03-08 20:28:32 -0500881bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800882 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400883 GLsizei width,
884 GLsizei height,
885 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400886 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400887 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400888 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400889 GLsizei imageSize)
890{
Jamie Madill43da7c42018-08-01 11:34:49 -0400891 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400892 if (pixelUnpackBuffer == nullptr && imageSize < 0)
893 {
894 // Checks are not required
895 return true;
896 }
897
898 // ...the data would be unpacked from the buffer object such that the memory reads required
899 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400900 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400901 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400902 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400903 const auto &unpack = context->getGLState().getUnpackState();
904
Jamie Madill7f232932018-09-12 11:03:06 -0400905 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
906 GLuint endByte = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400907 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400908 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400909 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400910 return false;
911 }
912
Geoff Langff5b2d52016-09-07 11:32:23 -0400913 if (pixelUnpackBuffer)
914 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400915 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400916 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
917 checkedEndByte += checkedOffset;
918
919 if (!checkedEndByte.IsValid() ||
920 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
921 {
922 // Overflow past the end of the buffer
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 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800926 if (context->getExtensions().webglCompatibility &&
927 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
928 {
929 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
930 PixelUnpackBufferBoundForTransformFeedback);
931 return false;
932 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400933 }
934 else
935 {
936 ASSERT(imageSize >= 0);
937 if (pixels == nullptr && imageSize != 0)
938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500939 context->handleError(InvalidOperation()
940 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400941 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400942 }
943
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400944 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500946 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400947 return false;
948 }
949 }
950
951 return true;
952}
953
Corentin Wallezad3ae902018-03-09 13:40:42 -0500954bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500955{
Geoff Lang37dde692014-01-31 16:34:54 -0500956 switch (queryType)
957 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500958 case QueryType::AnySamples:
959 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400960 return context->getClientMajorVersion() >= 3 ||
961 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500962 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800963 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500964 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800965 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500966 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800967 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500968 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800969 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800970 default:
971 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500972 }
973}
974
Jamie Madill5b772312018-03-08 20:28:32 -0500975bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400976 GLenum type,
977 GLboolean normalized,
978 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400979 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400980 bool pureInteger)
981{
982 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400983 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
984 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
985 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
986 // parameter exceeds 255.
987 constexpr GLsizei kMaxWebGLStride = 255;
988 if (stride > kMaxWebGLStride)
989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500990 context->handleError(InvalidValue()
991 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400992 return false;
993 }
994
995 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
996 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
997 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
998 // or an INVALID_OPERATION error is generated.
Frank Henigmand633b152018-10-04 23:34:31 -0400999 angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
1000 size_t typeSize = GetVertexFormatSize(internalType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001001
1002 ASSERT(isPow2(typeSize) && typeSize > 0);
1003 size_t sizeMask = (typeSize - 1);
1004 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001007 return false;
1008 }
1009
1010 if ((stride & sizeMask) != 0)
1011 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001012 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001013 return false;
1014 }
1015
1016 return true;
1017}
1018
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001019Program *GetValidProgramNoResolve(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001020{
He Yunchaoced53ae2016-11-29 15:00:51 +08001021 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1022 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1023 // or program object and INVALID_OPERATION if the provided name identifies an object
1024 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001025
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001026 Program *validProgram = context->getProgramNoResolveLink(id);
Dian Xiang769769a2015-09-09 15:20:08 -07001027
1028 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001029 {
Dian Xiang769769a2015-09-09 15:20:08 -07001030 if (context->getShader(id))
1031 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001032 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001033 }
1034 else
1035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001036 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001037 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001038 }
Dian Xiang769769a2015-09-09 15:20:08 -07001039
1040 return validProgram;
1041}
1042
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001043Program *GetValidProgram(Context *context, GLuint id)
1044{
1045 Program *program = GetValidProgramNoResolve(context, id);
1046 if (program)
1047 {
Jamie Madill785e8a02018-10-04 17:42:00 -04001048 program->resolveLink(context);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001049 }
1050 return program;
1051}
1052
Jamie Madill5b772312018-03-08 20:28:32 -05001053Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001054{
1055 // See ValidProgram for spec details.
1056
1057 Shader *validShader = context->getShader(id);
1058
1059 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001060 {
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001061 if (context->getProgramNoResolveLink(id))
Dian Xiang769769a2015-09-09 15:20:08 -07001062 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001063 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001064 }
1065 else
1066 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001067 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001068 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001069 }
Dian Xiang769769a2015-09-09 15:20:08 -07001070
1071 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001072}
1073
Jamie Madill43da7c42018-08-01 11:34:49 -04001074bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001075{
Geoff Langfa125c92017-10-24 13:01:46 -04001076 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001077 {
Geoff Langfa125c92017-10-24 13:01:46 -04001078 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1079 {
1080 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1081 return false;
1082 }
Jamie Madillb4472272014-07-03 10:38:55 -04001083
Geoff Langfa125c92017-10-24 13:01:46 -04001084 // Color attachment 0 is validated below because it is always valid
1085 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001086 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001087 {
Geoff Langfa125c92017-10-24 13:01:46 -04001088 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001089 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001090 }
1091 }
1092 else
1093 {
1094 switch (attachment)
1095 {
Geoff Langfa125c92017-10-24 13:01:46 -04001096 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001097 case GL_DEPTH_ATTACHMENT:
1098 case GL_STENCIL_ATTACHMENT:
1099 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001100
He Yunchaoced53ae2016-11-29 15:00:51 +08001101 case GL_DEPTH_STENCIL_ATTACHMENT:
1102 if (!context->getExtensions().webglCompatibility &&
1103 context->getClientMajorVersion() < 3)
1104 {
Geoff Langfa125c92017-10-24 13:01:46 -04001105 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001106 return false;
1107 }
1108 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001109
He Yunchaoced53ae2016-11-29 15:00:51 +08001110 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001112 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001113 }
1114 }
1115
1116 return true;
1117}
1118
Jamie Madill5b772312018-03-08 20:28:32 -05001119bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 GLenum target,
1121 GLsizei samples,
1122 GLenum internalformat,
1123 GLsizei width,
1124 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001125{
1126 switch (target)
1127 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001128 case GL_RENDERBUFFER:
1129 break;
1130 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001131 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001132 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133 }
1134
1135 if (width < 0 || height < 0 || samples < 0)
1136 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001137 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001138 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139 }
1140
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001141 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1142 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1143
1144 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001145 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001146 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001147 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001148 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001149 }
1150
1151 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1152 // 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 -08001153 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001154 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001155 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001157 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001158 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001159 }
1160
Geoff Langaae65a42014-05-26 12:43:44 -04001161 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001163 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001164 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001165 }
1166
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001167 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001168 if (handle == 0)
1169 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001171 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001172 }
1173
1174 return true;
1175}
1176
Jamie Madill43da7c42018-08-01 11:34:49 -04001177bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001178 GLenum target,
1179 GLenum attachment,
1180 GLenum renderbuffertarget,
1181 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001182{
Geoff Lange8afa902017-09-27 15:00:43 -04001183 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001185 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001186 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001187 }
1188
Jamie Madill43da7c42018-08-01 11:34:49 -04001189 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001190
Jamie Madill84115c92015-04-23 15:00:07 -04001191 ASSERT(framebuffer);
1192 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001193 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001194 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001195 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001196 }
1197
Jamie Madillb4472272014-07-03 10:38:55 -04001198 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001199 {
Jamie Madillb4472272014-07-03 10:38:55 -04001200 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001201 }
1202
Jamie Madillab9d82c2014-01-21 16:38:14 -05001203 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1204 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1205 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1206 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1207 if (renderbuffer != 0)
1208 {
1209 if (!context->getRenderbuffer(renderbuffer))
1210 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001211 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001212 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001213 }
1214 }
1215
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001216 return true;
1217}
1218
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001219bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001220 GLint srcX0,
1221 GLint srcY0,
1222 GLint srcX1,
1223 GLint srcY1,
1224 GLint dstX0,
1225 GLint dstY0,
1226 GLint dstX1,
1227 GLint dstY1,
1228 GLbitfield mask,
1229 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001230{
1231 switch (filter)
1232 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001233 case GL_NEAREST:
1234 break;
1235 case GL_LINEAR:
1236 break;
1237 default:
Olli Etuahof0e3c192018-08-15 13:37:21 +03001238 ANGLE_VALIDATION_ERR(context, InvalidEnum(), BlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001239 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001240 }
1241
1242 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1243 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001244 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001245 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246 }
1247
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001248 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1249 // color buffer, leaving only nearest being unfiltered from above
1250 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1251 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001252 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 }
1255
Jamie Madill7f232932018-09-12 11:03:06 -04001256 const auto &glState = context->getGLState();
1257 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1258 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001259
1260 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001262 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001263 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001264 }
1265
Jamie Madill427064d2018-04-13 16:20:34 -04001266 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001267 {
Jamie Madill48faf802014-11-06 15:27:22 -05001268 return false;
1269 }
1270
Jamie Madill427064d2018-04-13 16:20:34 -04001271 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001272 {
Jamie Madill48faf802014-11-06 15:27:22 -05001273 return false;
1274 }
1275
Qin Jiajiaaef92162018-02-27 13:51:44 +08001276 if (readFramebuffer->id() == drawFramebuffer->id())
1277 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001278 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001279 return false;
1280 }
1281
Jamie Madille98b1b52018-03-08 09:47:23 -05001282 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001283 {
Geoff Langb1196682014-07-23 13:47:29 -04001284 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001285 }
1286
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001287 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1288 // always run it in order to avoid triggering driver bugs.
1289 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1290 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001291 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001292 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1293 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001294 }
1295
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001296 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1297
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001298 if (mask & GL_COLOR_BUFFER_BIT)
1299 {
Jamie Madill7f232932018-09-12 11:03:06 -04001300 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1301 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001302
He Yunchao66a41a22016-12-15 16:45:05 +08001303 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001305 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306
Geoff Langa15472a2015-08-11 11:48:03 -04001307 for (size_t drawbufferIdx = 0;
1308 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001309 {
Geoff Langa15472a2015-08-11 11:48:03 -04001310 const FramebufferAttachment *attachment =
1311 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1312 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001313 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001314 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001315
Geoff Langb2f3d052013-08-13 12:49:27 -04001316 // The GL ES 3.0.2 spec (pg 193) states that:
1317 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001318 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1319 // as well
1320 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1321 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001322 // Changes with EXT_color_buffer_float:
1323 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001324 GLenum readComponentType = readFormat.info->componentType;
1325 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001326 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001327 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001328 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001329 drawComponentType == GL_SIGNED_NORMALIZED);
1330
1331 if (extensions.colorBufferFloat)
1332 {
1333 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1334 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1335
1336 if (readFixedOrFloat != drawFixedOrFloat)
1337 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001338 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1339 BlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001340 return false;
1341 }
1342 }
1343 else if (readFixedPoint != drawFixedPoint)
1344 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001345 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1346 BlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001347 return false;
1348 }
1349
1350 if (readComponentType == GL_UNSIGNED_INT &&
1351 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001353 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1354 BlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001355 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001356 }
1357
Jamie Madill6163c752015-12-07 16:32:59 -05001358 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001360 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1361 BlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001362 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 }
1364
Jamie Madilla3944d42016-07-22 22:13:26 -04001365 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001366 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001368 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1369 BlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001370 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 }
Geoff Lange4915782017-04-12 15:19:07 -04001372
1373 if (context->getExtensions().webglCompatibility &&
1374 *readColorBuffer == *attachment)
1375 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001376 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001377 return false;
1378 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 }
1380 }
1381
Jamie Madilla3944d42016-07-22 22:13:26 -04001382 if ((readFormat.info->componentType == GL_INT ||
1383 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1384 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001386 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001387 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
He Yunchao66a41a22016-12-15 16:45:05 +08001390 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1391 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1392 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1393 // situation is an application error that would lead to a crash in ANGLE.
1394 else if (drawFramebuffer->hasEnabledDrawBuffer())
1395 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001396 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001397 return false;
1398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 }
1400
He Yunchaoced53ae2016-11-29 15:00:51 +08001401 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001402 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1403 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001405 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001407 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001408 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001409 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001410 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001412 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 {
Kenneth Russell69382852017-07-21 16:38:44 -04001414 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001415 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001416 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1417 BlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001419 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001420
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001421 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001423 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1424 BlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001425 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 }
Geoff Lange4915782017-04-12 15:19:07 -04001427
1428 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1429 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001430 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001431 return false;
1432 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 }
He Yunchao66a41a22016-12-15 16:45:05 +08001434 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1435 else if (drawBuffer)
1436 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001437 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001438 return false;
1439 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001440 }
1441 }
1442
Martin Radeva3ed4572017-07-27 18:29:37 +03001443 // ANGLE_multiview, Revision 1:
1444 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001445 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1446 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1447 // views in the current read framebuffer is more than one.
1448 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001449 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001450 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001451 return false;
1452 }
1453 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1454 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001455 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001456 return false;
1457 }
1458
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001459 return true;
1460}
1461
Jamie Madill4928b7c2017-06-20 12:57:39 -04001462bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001463 GLint x,
1464 GLint y,
1465 GLsizei width,
1466 GLsizei height,
1467 GLenum format,
1468 GLenum type,
1469 GLsizei bufSize,
1470 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001471 GLsizei *columns,
1472 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001473 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001474{
1475 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001476 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001477 return false;
1478 }
1479
Brandon Jonesd1049182018-03-28 10:02:20 -07001480 GLsizei writeLength = 0;
1481 GLsizei writeColumns = 0;
1482 GLsizei writeRows = 0;
1483
1484 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1485 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001486 {
Geoff Langb1196682014-07-23 13:47:29 -04001487 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001488 }
1489
Brandon Jonesd1049182018-03-28 10:02:20 -07001490 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001491 {
Geoff Langb1196682014-07-23 13:47:29 -04001492 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001493 }
1494
Brandon Jonesd1049182018-03-28 10:02:20 -07001495 SetRobustLengthParam(length, writeLength);
1496 SetRobustLengthParam(columns, writeColumns);
1497 SetRobustLengthParam(rows, writeRows);
1498
Jamie Madillc29968b2016-01-20 11:17:23 -05001499 return true;
1500}
1501
1502bool ValidateReadnPixelsEXT(Context *context,
1503 GLint x,
1504 GLint y,
1505 GLsizei width,
1506 GLsizei height,
1507 GLenum format,
1508 GLenum type,
1509 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001510 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001511{
1512 if (bufSize < 0)
1513 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001514 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001515 return false;
1516 }
1517
Geoff Lang62fce5b2016-09-30 10:46:35 -04001518 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001519 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001520}
Jamie Madill26e91952014-03-05 15:01:27 -05001521
Jamie Madill4928b7c2017-06-20 12:57:39 -04001522bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001523 GLint x,
1524 GLint y,
1525 GLsizei width,
1526 GLsizei height,
1527 GLenum format,
1528 GLenum type,
1529 GLsizei bufSize,
1530 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001531 GLsizei *columns,
1532 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001533 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001534{
Brandon Jonesd1049182018-03-28 10:02:20 -07001535 GLsizei writeLength = 0;
1536 GLsizei writeColumns = 0;
1537 GLsizei writeRows = 0;
1538
Geoff Lang62fce5b2016-09-30 10:46:35 -04001539 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001540 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001541 return false;
1542 }
1543
Brandon Jonesd1049182018-03-28 10:02:20 -07001544 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1545 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001546 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001547 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001548 }
1549
Brandon Jonesd1049182018-03-28 10:02:20 -07001550 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001551 {
1552 return false;
1553 }
1554
Brandon Jonesd1049182018-03-28 10:02:20 -07001555 SetRobustLengthParam(length, writeLength);
1556 SetRobustLengthParam(columns, writeColumns);
1557 SetRobustLengthParam(rows, writeRows);
1558
Geoff Lang62fce5b2016-09-30 10:46:35 -04001559 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001560}
1561
Jamie Madill43da7c42018-08-01 11:34:49 -04001562bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001563{
1564 if (!context->getExtensions().occlusionQueryBoolean &&
1565 !context->getExtensions().disjointTimerQuery)
1566 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001567 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001568 return false;
1569 }
1570
Olli Etuaho41997e72016-03-10 13:38:39 +02001571 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001572}
1573
Jamie Madill43da7c42018-08-01 11:34:49 -04001574bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001575{
1576 if (!context->getExtensions().occlusionQueryBoolean &&
1577 !context->getExtensions().disjointTimerQuery)
1578 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001579 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001580 return false;
1581 }
1582
Olli Etuaho41997e72016-03-10 13:38:39 +02001583 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001584}
1585
Jamie Madill43da7c42018-08-01 11:34:49 -04001586bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001587{
1588 if (!context->getExtensions().occlusionQueryBoolean &&
1589 !context->getExtensions().disjointTimerQuery)
1590 {
1591 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1592 return false;
1593 }
1594
1595 return true;
1596}
1597
Jamie Madill43da7c42018-08-01 11:34:49 -04001598bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001599{
1600 if (!ValidQueryType(context, target))
1601 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001602 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001603 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001604 }
1605
1606 if (id == 0)
1607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001608 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001609 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001610 }
1611
1612 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1613 // of zero, if the active query object name for <target> is non-zero (for the
1614 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1615 // the active query for either target is non-zero), if <id> is the name of an
1616 // existing query object whose type does not match <target>, or if <id> is the
1617 // active query object name for any query type, the error INVALID_OPERATION is
1618 // generated.
1619
1620 // Ensure no other queries are active
1621 // NOTE: If other queries than occlusion are supported, we will need to check
1622 // separately that:
1623 // a) The query ID passed is not the current active query for any target/type
1624 // b) There are no active queries for the requested target (and in the case
1625 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1626 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001627
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001628 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001630 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001631 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001632 }
1633
1634 Query *queryObject = context->getQuery(id, true, target);
1635
1636 // check that name was obtained with glGenQueries
1637 if (!queryObject)
1638 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001639 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001640 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001641 }
1642
1643 // check for type mismatch
1644 if (queryObject->getType() != target)
1645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001646 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001647 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001648 }
1649
1650 return true;
1651}
1652
Jamie Madill43da7c42018-08-01 11:34:49 -04001653bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654{
1655 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001656 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001657 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001658 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001659 return false;
1660 }
1661
1662 return ValidateBeginQueryBase(context, target, id);
1663}
1664
Jamie Madill43da7c42018-08-01 11:34:49 -04001665bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001666{
1667 if (!ValidQueryType(context, target))
1668 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001669 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001670 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001671 }
1672
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001673 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001674
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001675 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001677 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001678 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001679 }
1680
Jamie Madill45c785d2014-05-13 14:09:34 -04001681 return true;
1682}
1683
Jamie Madill43da7c42018-08-01 11:34:49 -04001684bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001685{
1686 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001687 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001688 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001689 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001690 return false;
1691 }
1692
1693 return ValidateEndQueryBase(context, target);
1694}
1695
Corentin Wallezad3ae902018-03-09 13:40:42 -05001696bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697{
1698 if (!context->getExtensions().disjointTimerQuery)
1699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001700 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001701 return false;
1702 }
1703
Corentin Wallezad3ae902018-03-09 13:40:42 -05001704 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001706 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001707 return false;
1708 }
1709
1710 Query *queryObject = context->getQuery(id, true, target);
1711 if (queryObject == nullptr)
1712 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001713 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001714 return false;
1715 }
1716
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001717 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001718 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001719 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001720 return false;
1721 }
1722
1723 return true;
1724}
1725
Corentin Wallezad3ae902018-03-09 13:40:42 -05001726bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001727{
Geoff Lang2186c382016-10-14 10:54:54 -04001728 if (numParams)
1729 {
1730 *numParams = 0;
1731 }
1732
Corentin Wallezad3ae902018-03-09 13:40:42 -05001733 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001734 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736 return false;
1737 }
1738
1739 switch (pname)
1740 {
1741 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001742 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001744 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001745 return false;
1746 }
1747 break;
1748 case GL_QUERY_COUNTER_BITS_EXT:
1749 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001750 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001751 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 return false;
1754 }
1755 break;
1756 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758 return false;
1759 }
1760
Geoff Lang2186c382016-10-14 10:54:54 -04001761 if (numParams)
1762 {
1763 // All queries return only one value
1764 *numParams = 1;
1765 }
1766
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767 return true;
1768}
1769
Corentin Wallezad3ae902018-03-09 13:40:42 -05001770bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001771{
1772 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001773 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001774 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001775 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001776 return false;
1777 }
1778
Geoff Lang2186c382016-10-14 10:54:54 -04001779 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001780}
1781
Geoff Lang2186c382016-10-14 10:54:54 -04001782bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001783 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001784 GLenum pname,
1785 GLsizei bufSize,
1786 GLsizei *length,
1787 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788{
Geoff Lang2186c382016-10-14 10:54:54 -04001789 if (!ValidateRobustEntryPoint(context, bufSize))
1790 {
1791 return false;
1792 }
1793
Brandon Jonesd1049182018-03-28 10:02:20 -07001794 GLsizei numParams = 0;
1795
1796 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001797 {
1798 return false;
1799 }
1800
Brandon Jonesd1049182018-03-28 10:02:20 -07001801 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001802 {
1803 return false;
1804 }
1805
Brandon Jonesd1049182018-03-28 10:02:20 -07001806 SetRobustLengthParam(length, numParams);
1807
Geoff Lang2186c382016-10-14 10:54:54 -04001808 return true;
1809}
1810
1811bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1812{
1813 if (numParams)
1814 {
1815 *numParams = 0;
1816 }
1817
Corentin Wallezad3ae902018-03-09 13:40:42 -05001818 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819
1820 if (!queryObject)
1821 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001822 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001823 return false;
1824 }
1825
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001826 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001828 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001829 return false;
1830 }
1831
1832 switch (pname)
1833 {
1834 case GL_QUERY_RESULT_EXT:
1835 case GL_QUERY_RESULT_AVAILABLE_EXT:
1836 break;
1837
1838 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001839 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001840 return false;
1841 }
1842
Geoff Lang2186c382016-10-14 10:54:54 -04001843 if (numParams)
1844 {
1845 *numParams = 1;
1846 }
1847
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001848 return true;
1849}
1850
1851bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1852{
1853 if (!context->getExtensions().disjointTimerQuery)
1854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001855 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001856 return false;
1857 }
Geoff Lang2186c382016-10-14 10:54:54 -04001858 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1859}
1860
1861bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1862 GLuint id,
1863 GLenum pname,
1864 GLsizei bufSize,
1865 GLsizei *length,
1866 GLint *params)
1867{
1868 if (!context->getExtensions().disjointTimerQuery)
1869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001870 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001871 return false;
1872 }
1873
1874 if (!ValidateRobustEntryPoint(context, bufSize))
1875 {
1876 return false;
1877 }
1878
Brandon Jonesd1049182018-03-28 10:02:20 -07001879 GLsizei numParams = 0;
1880
1881 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001882 {
1883 return false;
1884 }
1885
Brandon Jonesd1049182018-03-28 10:02:20 -07001886 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001887 {
1888 return false;
1889 }
1890
Brandon Jonesd1049182018-03-28 10:02:20 -07001891 SetRobustLengthParam(length, numParams);
1892
Geoff Lang2186c382016-10-14 10:54:54 -04001893 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001894}
1895
1896bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1897{
1898 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001899 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001900 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001902 return false;
1903 }
Geoff Lang2186c382016-10-14 10:54:54 -04001904 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1905}
1906
1907bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1908 GLuint id,
1909 GLenum pname,
1910 GLsizei bufSize,
1911 GLsizei *length,
1912 GLuint *params)
1913{
1914 if (!context->getExtensions().disjointTimerQuery &&
1915 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1916 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001917 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001918 return false;
1919 }
1920
1921 if (!ValidateRobustEntryPoint(context, bufSize))
1922 {
1923 return false;
1924 }
1925
Brandon Jonesd1049182018-03-28 10:02:20 -07001926 GLsizei numParams = 0;
1927
1928 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001929 {
1930 return false;
1931 }
1932
Brandon Jonesd1049182018-03-28 10:02:20 -07001933 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001934 {
1935 return false;
1936 }
1937
Brandon Jonesd1049182018-03-28 10:02:20 -07001938 SetRobustLengthParam(length, numParams);
1939
Geoff Lang2186c382016-10-14 10:54:54 -04001940 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001941}
1942
1943bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1944{
1945 if (!context->getExtensions().disjointTimerQuery)
1946 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001947 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001948 return false;
1949 }
Geoff Lang2186c382016-10-14 10:54:54 -04001950 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1951}
1952
1953bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1954 GLuint id,
1955 GLenum pname,
1956 GLsizei bufSize,
1957 GLsizei *length,
1958 GLint64 *params)
1959{
1960 if (!context->getExtensions().disjointTimerQuery)
1961 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001962 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001963 return false;
1964 }
1965
1966 if (!ValidateRobustEntryPoint(context, bufSize))
1967 {
1968 return false;
1969 }
1970
Brandon Jonesd1049182018-03-28 10:02:20 -07001971 GLsizei numParams = 0;
1972
1973 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001974 {
1975 return false;
1976 }
1977
Brandon Jonesd1049182018-03-28 10:02:20 -07001978 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001979 {
1980 return false;
1981 }
1982
Brandon Jonesd1049182018-03-28 10:02:20 -07001983 SetRobustLengthParam(length, numParams);
1984
Geoff Lang2186c382016-10-14 10:54:54 -04001985 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001986}
1987
1988bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1989{
1990 if (!context->getExtensions().disjointTimerQuery)
1991 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001992 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001993 return false;
1994 }
Geoff Lang2186c382016-10-14 10:54:54 -04001995 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1996}
1997
1998bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1999 GLuint id,
2000 GLenum pname,
2001 GLsizei bufSize,
2002 GLsizei *length,
2003 GLuint64 *params)
2004{
2005 if (!context->getExtensions().disjointTimerQuery)
2006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002008 return false;
2009 }
2010
2011 if (!ValidateRobustEntryPoint(context, bufSize))
2012 {
2013 return false;
2014 }
2015
Brandon Jonesd1049182018-03-28 10:02:20 -07002016 GLsizei numParams = 0;
2017
2018 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002019 {
2020 return false;
2021 }
2022
Brandon Jonesd1049182018-03-28 10:02:20 -07002023 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002024 {
2025 return false;
2026 }
2027
Brandon Jonesd1049182018-03-28 10:02:20 -07002028 SetRobustLengthParam(length, numParams);
2029
Geoff Lang2186c382016-10-14 10:54:54 -04002030 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002031}
2032
Jamie Madill5b772312018-03-08 20:28:32 -05002033bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002034 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002035 GLint location,
2036 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002037 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002038{
Jiajia Qin5451d532017-11-16 17:16:34 +08002039 // TODO(Jiajia): Add image uniform check in future.
2040 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002041 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002042 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002043 return false;
2044 }
2045
Jiajia Qin5451d532017-11-16 17:16:34 +08002046 if (!program)
2047 {
2048 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2049 return false;
2050 }
2051
2052 if (!program->isLinked())
2053 {
2054 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2055 return false;
2056 }
2057
2058 if (location == -1)
2059 {
2060 // Silently ignore the uniform command
2061 return false;
2062 }
2063
2064 const auto &uniformLocations = program->getUniformLocations();
2065 size_t castedLocation = static_cast<size_t>(location);
2066 if (castedLocation >= uniformLocations.size())
2067 {
2068 context->handleError(InvalidOperation() << "Invalid uniform location");
2069 return false;
2070 }
2071
2072 const auto &uniformLocation = uniformLocations[castedLocation];
2073 if (uniformLocation.ignored)
2074 {
2075 // Silently ignore the uniform command
2076 return false;
2077 }
2078
2079 if (!uniformLocation.used())
2080 {
2081 context->handleError(InvalidOperation());
2082 return false;
2083 }
2084
2085 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2086
2087 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002088 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002089 {
2090 context->handleError(InvalidOperation());
2091 return false;
2092 }
2093
2094 *uniformOut = &uniform;
2095 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002096}
2097
Jamie Madill5b772312018-03-08 20:28:32 -05002098bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002099 GLenum uniformType,
2100 GLsizei count,
2101 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002102{
Jiajia Qin5451d532017-11-16 17:16:34 +08002103 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2104 // It is compatible with INT or BOOL.
2105 // Do these cheap tests first, for a little extra speed.
2106 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002107 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002108 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002109 }
2110
Jiajia Qin5451d532017-11-16 17:16:34 +08002111 if (IsSamplerType(uniformType))
2112 {
2113 // Check that the values are in range.
2114 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2115 for (GLsizei i = 0; i < count; ++i)
2116 {
2117 if (value[i] < 0 || value[i] >= max)
2118 {
2119 context->handleError(InvalidValue() << "sampler uniform value out of range");
2120 return false;
2121 }
2122 }
2123 return true;
2124 }
2125
2126 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2127 return false;
2128}
2129
Jamie Madill5b772312018-03-08 20:28:32 -05002130bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002131{
2132 // Check that the value type is compatible with uniform type.
2133 if (valueType == uniformType)
2134 {
2135 return true;
2136 }
2137
2138 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2139 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002140}
2141
Jamie Madill5b772312018-03-08 20:28:32 -05002142bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002143{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002144 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002145 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002146 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2147 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002148}
2149
Jamie Madill5b772312018-03-08 20:28:32 -05002150bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002151{
2152 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002153 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmana98a6472017-02-02 21:38:32 -05002154 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2155 ValidateUniform1ivValue(context, uniform->type, count, value);
2156}
2157
Jamie Madill5b772312018-03-08 20:28:32 -05002158bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002159 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002160 GLint location,
2161 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002162 GLboolean transpose)
2163{
Geoff Lang92019432017-11-20 13:09:34 -05002164 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002166 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002167 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002168 }
2169
Jamie Madill62d31cb2015-09-11 13:25:51 -04002170 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002171 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002172 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2173 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002174}
2175
Jamie Madill5b772312018-03-08 20:28:32 -05002176bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002177{
2178 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002180 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002181 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002182 }
2183
Jamie Madill0af26e12015-03-05 19:54:33 -05002184 const Caps &caps = context->getCaps();
2185
Jamie Madill893ab082014-05-16 16:56:10 -04002186 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2187 {
2188 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2189
Jamie Madill0af26e12015-03-05 19:54:33 -05002190 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002192 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002193 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002194 }
2195 }
2196
2197 switch (pname)
2198 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002199 case GL_TEXTURE_BINDING_2D:
2200 case GL_TEXTURE_BINDING_CUBE_MAP:
2201 case GL_TEXTURE_BINDING_3D:
2202 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002203 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002204 break;
Olli Etuahod310a432018-08-24 15:40:23 +03002205 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
Olli Etuaho064458a2018-08-30 14:02:02 +03002206 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03002207 {
2208 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
2209 return false;
2210 }
2211 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002212 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2213 if (!context->getExtensions().textureRectangle)
2214 {
2215 context->handleError(InvalidEnum()
2216 << "ANGLE_texture_rectangle extension not present");
2217 return false;
2218 }
2219 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002220 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2221 if (!context->getExtensions().eglStreamConsumerExternal &&
2222 !context->getExtensions().eglImageExternal)
2223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002224 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2225 "nor GL_OES_EGL_image_external "
2226 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002227 return false;
2228 }
2229 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002230
He Yunchaoced53ae2016-11-29 15:00:51 +08002231 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2232 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002233 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002234 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2235 ASSERT(readFramebuffer);
2236
Jamie Madill427064d2018-04-13 16:20:34 -04002237 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002238 {
Geoff Langb1196682014-07-23 13:47:29 -04002239 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002240 }
2241
Jamie Madille98b1b52018-03-08 09:47:23 -05002242 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002243 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002245 return false;
2246 }
2247
Jamie Madille98b1b52018-03-08 09:47:23 -05002248 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002249 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002251 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002252 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002253 }
2254 }
2255 break;
2256
He Yunchaoced53ae2016-11-29 15:00:51 +08002257 default:
2258 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002259 }
2260
2261 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002262 if (*numParams == 0)
2263 {
2264 return false;
2265 }
2266
2267 return true;
2268}
2269
Brandon Jonesd1049182018-03-28 10:02:20 -07002270bool ValidateGetBooleanvRobustANGLE(Context *context,
2271 GLenum pname,
2272 GLsizei bufSize,
2273 GLsizei *length,
2274 GLboolean *params)
2275{
2276 GLenum nativeType;
2277 unsigned int numParams = 0;
2278
2279 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2280 {
2281 return false;
2282 }
2283
2284 SetRobustLengthParam(length, numParams);
2285
2286 return true;
2287}
2288
2289bool ValidateGetFloatvRobustANGLE(Context *context,
2290 GLenum pname,
2291 GLsizei bufSize,
2292 GLsizei *length,
2293 GLfloat *params)
2294{
2295 GLenum nativeType;
2296 unsigned int numParams = 0;
2297
2298 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2299 {
2300 return false;
2301 }
2302
2303 SetRobustLengthParam(length, numParams);
2304
2305 return true;
2306}
2307
2308bool ValidateGetIntegervRobustANGLE(Context *context,
2309 GLenum pname,
2310 GLsizei bufSize,
2311 GLsizei *length,
2312 GLint *data)
2313{
2314 GLenum nativeType;
2315 unsigned int numParams = 0;
2316
2317 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2318 {
2319 return false;
2320 }
2321
2322 SetRobustLengthParam(length, numParams);
2323
2324 return true;
2325}
2326
2327bool ValidateGetInteger64vRobustANGLE(Context *context,
2328 GLenum pname,
2329 GLsizei bufSize,
2330 GLsizei *length,
2331 GLint64 *data)
2332{
2333 GLenum nativeType;
2334 unsigned int numParams = 0;
2335
2336 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2337 {
2338 return false;
2339 }
2340
2341 if (nativeType == GL_INT_64_ANGLEX)
2342 {
2343 CastStateValues(context, nativeType, pname, numParams, data);
2344 return false;
2345 }
2346
2347 SetRobustLengthParam(length, numParams);
2348 return true;
2349}
2350
Jamie Madill5b772312018-03-08 20:28:32 -05002351bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002352 GLenum pname,
2353 GLsizei bufSize,
2354 GLenum *nativeType,
2355 unsigned int *numParams)
2356{
2357 if (!ValidateRobustEntryPoint(context, bufSize))
2358 {
2359 return false;
2360 }
2361
2362 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2363 {
2364 return false;
2365 }
2366
2367 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002368 {
2369 return false;
2370 }
2371
2372 return true;
2373}
2374
Jamie Madill5b772312018-03-08 20:28:32 -05002375bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002376 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002377 GLint level,
2378 GLenum internalformat,
2379 bool isSubImage,
2380 GLint xoffset,
2381 GLint yoffset,
2382 GLint zoffset,
2383 GLint x,
2384 GLint y,
2385 GLsizei width,
2386 GLsizei height,
2387 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002388 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002389{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002390 TextureType texType = TextureTargetToType(target);
2391
Brandon Jones6cad5662017-06-14 13:25:13 -07002392 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002393 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002394 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2395 return false;
2396 }
2397
2398 if (width < 0 || height < 0)
2399 {
2400 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002401 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002402 }
2403
He Yunchaoced53ae2016-11-29 15:00:51 +08002404 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2405 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002407 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002408 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002409 }
2410
2411 if (border != 0)
2412 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002413 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002414 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002415 }
2416
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002417 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002418 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002419 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002420 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002421 }
2422
Jamie Madill43da7c42018-08-01 11:34:49 -04002423 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002424 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002425 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002426 {
Geoff Langb1196682014-07-23 13:47:29 -04002427 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002428 }
2429
Jamie Madille98b1b52018-03-08 09:47:23 -05002430 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002431 {
Geoff Langb1196682014-07-23 13:47:29 -04002432 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002433 }
2434
Martin Radev138064f2016-07-15 12:03:41 +03002435 if (readFramebuffer->getReadBufferState() == GL_NONE)
2436 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002437 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002438 return false;
2439 }
2440
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002441 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2442 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002443 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002444 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002445 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2446 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002447 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002448 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002449 return false;
2450 }
2451
Martin Radev04e2c3b2017-07-27 16:54:35 +03002452 // ANGLE_multiview spec, Revision 1:
2453 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2454 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002455 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2456 // framebuffer is more than one.
2457 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002458 {
2459 context->handleError(InvalidFramebufferOperation()
2460 << "The active read framebuffer object has multiview attachments.");
2461 return false;
2462 }
2463
Jamie Madill43da7c42018-08-01 11:34:49 -04002464 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002465
Geoff Langaae65a42014-05-26 12:43:44 -04002466 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002467 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002468 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002469 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002470 maxDimension = caps.max2DTextureSize;
2471 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002472
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002473 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002474 maxDimension = caps.maxCubeMapTextureSize;
2475 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002476
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002477 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002478 maxDimension = caps.maxRectangleTextureSize;
2479 break;
2480
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002481 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002482 maxDimension = caps.max2DTextureSize;
2483 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002484
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002485 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002486 maxDimension = caps.max3DTextureSize;
2487 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002488
He Yunchaoced53ae2016-11-29 15:00:51 +08002489 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002490 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002491 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002492 }
2493
Jamie Madill43da7c42018-08-01 11:34:49 -04002494 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002495 if (!texture)
2496 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002497 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002498 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002499 }
2500
Geoff Lang69cce582015-09-17 13:20:36 -04002501 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002503 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002504 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002505 }
2506
Jamie Madill43da7c42018-08-01 11:34:49 -04002507 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002508 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002509 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002510
Geoff Lang966c9402017-04-18 12:38:27 -04002511 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002513 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002514 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002515 }
2516
2517 if (isSubImage)
2518 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002519 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2520 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2521 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002523 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002524 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002525 }
2526 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002527 else
2528 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002529 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002530 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002531 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002532 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002533 }
2534
Geoff Langeb66a6e2016-10-31 13:06:12 -04002535 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002536 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002537 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002538 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002539 }
2540
2541 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002542 if (static_cast<int>(width) > maxLevelDimension ||
2543 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002544 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002545 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002546 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002547 }
2548 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002549
Jamie Madill0c8abca2016-07-22 20:21:26 -04002550 if (textureFormatOut)
2551 {
2552 *textureFormatOut = texture->getFormat(target, level);
2553 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002554
2555 // Detect texture copying feedback loops for WebGL.
2556 if (context->getExtensions().webglCompatibility)
2557 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002558 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002559 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002560 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002561 return false;
2562 }
2563 }
2564
Jamie Madill560a8d82014-05-21 13:06:20 -04002565 return true;
2566}
2567
Jamie Madillb42162f2018-08-20 12:58:37 -04002568// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2569// completeness check.
2570const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002571{
2572 const Extensions &extensions = context->getExtensions();
Jamie Madill7f232932018-09-12 11:03:06 -04002573 const State &state = context->getGLState();
Jamie Madille7d80f32018-08-08 15:49:23 -04002574
2575 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2576 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2577 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madilld84b6732018-09-06 15:54:35 -04002578 VertexArray *vertexArray = state.getVertexArray();
2579 ASSERT(vertexArray);
2580
2581 if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
Jamie Madille7d80f32018-08-08 15:49:23 -04002582 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002583 return kErrorBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002584 }
2585
2586 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2587 // Section 6.10 of the WebGL 1.0 spec.
2588 Framebuffer *framebuffer = state.getDrawFramebuffer();
Jamie Madilld84b6732018-09-06 15:54:35 -04002589 ASSERT(framebuffer);
2590
Jamie Madille7d80f32018-08-08 15:49:23 -04002591 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2592 {
2593 ASSERT(framebuffer);
2594 const FramebufferAttachment *dsAttachment =
2595 framebuffer->getStencilOrDepthStencilAttachment();
2596 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2597 ASSERT(stencilBits <= 8);
2598
2599 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2600 if (depthStencilState.stencilTest && stencilBits > 0)
2601 {
2602 GLuint maxStencilValue = (1 << stencilBits) - 1;
2603
2604 bool differentRefs =
2605 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2606 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2607 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2608 (depthStencilState.stencilBackWritemask & maxStencilValue);
2609 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2610 (depthStencilState.stencilBackMask & maxStencilValue);
2611
2612 if (differentRefs || differentWritemasks || differentMasks)
2613 {
2614 if (!extensions.webglCompatibility)
2615 {
2616 WARN() << "This ANGLE implementation does not support separate front/back "
2617 "stencil writemasks, reference values, or stencil mask values.";
2618 }
Jamie Madillb42162f2018-08-20 12:58:37 -04002619 return kErrorStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002620 }
2621 }
2622 }
2623
2624 if (!framebuffer->isComplete(context))
2625 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002626 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2627 return kErrorDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002628 }
2629
2630 if (context->getStateCache().hasAnyEnabledClientAttrib())
2631 {
2632 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2633 {
2634 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2635 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2636 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2637 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madillb42162f2018-08-20 12:58:37 -04002638 return kErrorVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002639 }
2640
2641 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2642 {
2643 // This is an application error that would normally result in a crash, but we catch it
2644 // and return an error
Jamie Madillb42162f2018-08-20 12:58:37 -04002645 return kErrorVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002646 }
2647 }
2648
2649 // If we are running GLES1, there is no current program.
2650 if (context->getClientVersion() >= Version(2, 0))
2651 {
Jamie Madill785e8a02018-10-04 17:42:00 -04002652 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002653 if (!program)
2654 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002655 return kErrorProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002656 }
2657
2658 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2659 // vertex shader stage or fragment shader stage is a undefined behaviour.
2660 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2661 // produce undefined result.
2662 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2663 !program->hasLinkedShaderStage(ShaderType::Fragment))
2664 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002665 return kErrorNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002666 }
2667
2668 if (!program->validateSamplers(nullptr, context->getCaps()))
2669 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002670 return kErrorTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002671 }
2672
2673 if (extensions.multiview)
2674 {
2675 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2676 const int framebufferNumViews = framebuffer->getNumViews();
2677 if (framebufferNumViews != programNumViews)
2678 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002679 return kErrorMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002680 }
2681
2682 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2683 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2684 framebufferNumViews > 1)
2685 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002686 return kErrorMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002687 }
2688
2689 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2690 state.isQueryActive(QueryType::TimeElapsed))
2691 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002692 return kErrorMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002693 }
2694 }
2695
2696 // Uniform buffer validation
2697 for (unsigned int uniformBlockIndex = 0;
2698 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2699 {
2700 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Jamie Madill7f232932018-09-12 11:03:06 -04002701 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Jamie Madille7d80f32018-08-08 15:49:23 -04002702 const OffsetBindingPointer<Buffer> &uniformBuffer =
2703 state.getIndexedUniformBuffer(blockBinding);
2704
2705 if (uniformBuffer.get() == nullptr)
2706 {
2707 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002708 return kErrorUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002709 }
2710
2711 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2712 if (uniformBufferSize < uniformBlock.dataSize)
2713 {
2714 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002715 return kErrorUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002716 }
2717
2718 if (extensions.webglCompatibility &&
2719 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2720 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002721 return kErrorUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002722 }
2723 }
2724
2725 // Do some additonal WebGL-specific validation
2726 if (extensions.webglCompatibility)
2727 {
2728 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2729 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2730 transformFeedbackObject->buffersBoundForOtherUse())
2731 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002732 return kErrorTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002733 }
2734
2735 // Detect rendering feedback loops for WebGL.
2736 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2737 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002738 return kErrorFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002739 }
2740
2741 // Detect that the vertex shader input types match the attribute types
2742 if (!ValidateVertexShaderAttributeTypeMatch(context))
2743 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002744 return kErrorVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002745 }
2746
2747 // Detect that the color buffer types match the fragment shader output types
2748 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2749 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002750 return kErrorDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002751 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002752
2753 const VertexArray *vao = context->getGLState().getVertexArray();
2754 if (vao->hasTransformFeedbackBindingConflict(context))
2755 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002756 return kErrorVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002757 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002758 }
2759 }
2760
Jamie Madillb42162f2018-08-20 12:58:37 -04002761 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002762}
2763
Jamie Madill16e28fd2018-09-12 11:03:05 -04002764bool ValidateDrawMode(Context *context, PrimitiveMode mode)
Jamie Madill250d33f2014-06-06 17:09:03 -04002765{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002766 const Extensions &extensions = context->getExtensions();
2767
Jamie Madill1aeb1312014-06-20 13:21:25 -04002768 switch (mode)
2769 {
Jamie Madill493f9572018-05-24 19:52:15 -04002770 case PrimitiveMode::Points:
2771 case PrimitiveMode::Lines:
2772 case PrimitiveMode::LineLoop:
2773 case PrimitiveMode::LineStrip:
2774 case PrimitiveMode::Triangles:
2775 case PrimitiveMode::TriangleStrip:
2776 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002777 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002778
Jamie Madill493f9572018-05-24 19:52:15 -04002779 case PrimitiveMode::LinesAdjacency:
2780 case PrimitiveMode::LineStripAdjacency:
2781 case PrimitiveMode::TrianglesAdjacency:
2782 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002783 if (!extensions.geometryShader)
2784 {
2785 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2786 return false;
2787 }
2788 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002789 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002790 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002791 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002792 }
2793
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002794 // If we are running GLES1, there is no current program.
2795 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002796 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002797 const State &state = context->getGLState();
2798
Jamie Madill785e8a02018-10-04 17:42:00 -04002799 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002800 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002801
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002802 // Do geometry shader specific validations
2803 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002804 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002805 if (!IsCompatibleDrawModeWithGeometryShader(
2806 mode, program->getGeometryShaderInputPrimitiveType()))
2807 {
2808 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2809 IncompatibleDrawModeAgainstGeometryShader);
2810 return false;
2811 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002812 }
2813 }
2814
Jamie Madill9fdaa492018-02-16 10:52:11 -05002815 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002816}
2817
Jamie Madill16e28fd2018-09-12 11:03:05 -04002818bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
2819{
2820 if (!context->getStateCache().isValidDrawMode(mode))
2821 {
2822 return ValidateDrawMode(context, mode);
2823 }
2824
2825 if (count < 0)
2826 {
2827 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2828 return false;
2829 }
2830
2831 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2832 if (drawStatesError)
2833 {
2834 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2835
2836 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2837 // Incomplete.
2838 GLenum errorCode =
2839 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2840 : GL_INVALID_OPERATION);
2841 context->handleError(Error(errorCode, errorMessage));
2842 return false;
2843 }
2844
2845 return true;
2846}
2847
Jamie Madill5b772312018-03-08 20:28:32 -05002848bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002849 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002850 GLint first,
2851 GLsizei count,
2852 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002853{
Jamie Madillfd716582014-06-06 17:09:04 -04002854 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002855 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002856 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002857 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002858 }
2859
Jamie Madill16e28fd2018-09-12 11:03:05 -04002860 if (count < 0)
2861 {
2862 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2863 return false;
2864 }
2865
Jamie Madill7f232932018-09-12 11:03:06 -04002866 const State &state = context->getGLState();
2867 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002868 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002869 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002870 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002871 if (!ValidateTransformFeedbackPrimitiveMode(context,
2872 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002873 {
James Darpinian30b604d2018-03-12 17:26:57 -07002874 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2875 return false;
2876 }
2877
2878 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2879 {
2880 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2881 return false;
2882 }
Jamie Madillfd716582014-06-06 17:09:04 -04002883 }
2884
Jamie Madill16e28fd2018-09-12 11:03:05 -04002885 if (!context->getStateCache().isValidDrawMode(mode))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002886 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002887 return ValidateDrawMode(context, mode);
2888 }
2889
2890 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2891 if (drawStatesError)
2892 {
2893 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2894
2895 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2896 // Incomplete.
2897 GLenum errorCode =
2898 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2899 : GL_INVALID_OPERATION);
2900 context->handleError(Error(errorCode, errorMessage));
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002901 return false;
2902 }
2903
Corentin Wallez71168a02016-12-19 15:11:18 -08002904 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002905 // - first < 0 has been checked as an error condition.
2906 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002907 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002908 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002909 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002910 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002911 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2912 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2913 {
2914 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2915 return false;
2916 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002917
Jamie Madill2da53562018-08-01 11:34:47 -04002918 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002919 {
2920 return false;
2921 }
Jamie Madillfd716582014-06-06 17:09:04 -04002922 }
2923
2924 return true;
2925}
2926
He Yunchaoced53ae2016-11-29 15:00:51 +08002927bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002928 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002929 GLint first,
2930 GLsizei count,
2931 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002932{
Geoff Lang63c5a592017-09-27 14:08:16 -04002933 if (!context->getExtensions().instancedArrays)
2934 {
2935 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2936 return false;
2937 }
2938
Corentin Wallez170efbf2017-05-02 13:45:01 -04002939 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002940 {
2941 return false;
2942 }
2943
Corentin Wallez0dc97812017-06-22 14:38:44 -04002944 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002945}
2946
Jamie Madill493f9572018-05-24 19:52:15 -04002947bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002948{
Jamie Madill250d33f2014-06-06 17:09:03 -04002949 switch (type)
2950 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002951 case GL_UNSIGNED_BYTE:
2952 case GL_UNSIGNED_SHORT:
2953 break;
2954 case GL_UNSIGNED_INT:
2955 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002958 return false;
2959 }
2960 break;
2961 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002962 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002963 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002964 }
2965
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002966 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002967
Jamie Madill43da7c42018-08-01 11:34:49 -04002968 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002969 if (curTransformFeedback && curTransformFeedback->isActive() &&
2970 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002971 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002972 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2973 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2974 if (context->getExtensions().geometryShader)
2975 {
2976 if (!ValidateTransformFeedbackPrimitiveMode(
2977 context, curTransformFeedback->getPrimitiveMode(), mode))
2978 {
2979 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2980 return false;
2981 }
2982 }
2983 else
2984 {
2985 // It is an invalid operation to call DrawElements, DrawRangeElements or
2986 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2987 // 86)
2988 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2989 UnsupportedDrawModeForTransformFeedback);
2990 return false;
2991 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002992 }
2993
Jiajia Qind9671222016-11-29 16:30:31 +08002994 return true;
2995}
2996
Jamie Madill5b772312018-03-08 20:28:32 -05002997bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002998 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002999 GLsizei count,
3000 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003001 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003002 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003003{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003004 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003005 return false;
3006
3007 const State &state = context->getGLState();
3008
Corentin Wallez170efbf2017-05-02 13:45:01 -04003009 if (!ValidateDrawBase(context, mode, count))
3010 {
3011 return false;
3012 }
3013
Jamie Madill43da7c42018-08-01 11:34:49 -04003014 const VertexArray *vao = state.getVertexArray();
Jamie Madillcd0a0a32018-10-18 18:41:57 -04003015 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003016
Jamie Madill43da7c42018-08-01 11:34:49 -04003017 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003018
3019 if (context->getExtensions().webglCompatibility)
3020 {
3021 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3022 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3023 {
3024 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3025 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3026 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003027 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003028 return false;
3029 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003030
3031 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3032 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3033 // error is generated.
3034 if (reinterpret_cast<intptr_t>(indices) < 0)
3035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003036 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003037 return false;
3038 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003039 }
Jamie Madillcc73f242018-08-01 11:34:48 -04003040 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
3041 {
3042 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3043 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3044 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3045 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3046 return false;
3047 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003048
3049 if (context->getExtensions().webglCompatibility ||
3050 !context->getGLState().areClientArraysEnabled())
3051 {
Brandon Jones2a018152018-06-08 15:59:26 -07003052 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003053 {
3054 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003055 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3056 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003057 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003058 return false;
3059 }
3060 }
3061
Jamie Madill9fdaa492018-02-16 10:52:11 -05003062 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003063 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003064 // This is an application error that would normally result in a crash, but we catch it and
3065 // return an error
3066 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3067 return false;
3068 }
3069
3070 if (count > 0 && elementArrayBuffer)
3071 {
3072 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3073 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3074 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3075 constexpr uint64_t kMaxTypeSize = 8;
3076 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3077 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3078 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3079
3080 uint64_t typeSize = typeBytes;
3081 uint64_t elementCount = static_cast<uint64_t>(count);
3082 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3083
3084 // Doing the multiplication here is overflow-safe
3085 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3086
3087 // The offset can be any value, check for overflows
3088 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3089 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003090 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3092 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003093 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003094
3095 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3096 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003097 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003098 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3099 return false;
3100 }
3101
3102 ASSERT(isPow2(typeSize) && typeSize > 0);
3103 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3104 {
3105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003106 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003107 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003108
3109 if (context->getExtensions().webglCompatibility &&
3110 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3111 {
3112 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3113 ElementArrayBufferBoundForTransformFeedback);
3114 return false;
3115 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003116 }
3117
Jamie Madill2da53562018-08-01 11:34:47 -04003118 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003119 {
3120 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003121 const DrawCallParams &params = context->getParams<DrawCallParams>();
3122 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3123 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003124
3125 // If we use an index greater than our maximum supported index range, return an error.
3126 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3127 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003128 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003129 {
3130 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3131 return false;
3132 }
3133
Jamie Madill2da53562018-08-01 11:34:47 -04003134 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003135 {
3136 return false;
3137 }
3138
3139 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003140 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003141 }
3142
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003143 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003144}
3145
Jamie Madill5b772312018-03-08 20:28:32 -05003146bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003147 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003148 GLsizei count,
3149 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003150 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003151 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003152{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003153 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003154}
3155
Geoff Lang3edfe032015-09-04 16:38:24 -04003156bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003157 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003158 GLsizei count,
3159 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003160 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003161 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003162{
Geoff Lang63c5a592017-09-27 14:08:16 -04003163 if (!context->getExtensions().instancedArrays)
3164 {
3165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3166 return false;
3167 }
3168
Corentin Wallez170efbf2017-05-02 13:45:01 -04003169 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003170 {
3171 return false;
3172 }
3173
Corentin Wallez0dc97812017-06-22 14:38:44 -04003174 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003175}
3176
He Yunchaoced53ae2016-11-29 15:00:51 +08003177bool ValidateFramebufferTextureBase(Context *context,
3178 GLenum target,
3179 GLenum attachment,
3180 GLuint texture,
3181 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003182{
Geoff Lange8afa902017-09-27 15:00:43 -04003183 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003184 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003185 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003186 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003187 }
3188
3189 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003190 {
3191 return false;
3192 }
3193
Jamie Madill55ec3b12014-07-03 10:38:57 -04003194 if (texture != 0)
3195 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003196 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003197
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003198 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003200 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003201 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003202 }
3203
3204 if (level < 0)
3205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003206 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003207 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003208 }
3209 }
3210
Jamie Madill43da7c42018-08-01 11:34:49 -04003211 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003212 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003213
Jamie Madill84115c92015-04-23 15:00:07 -04003214 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003215 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003216 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003217 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003218 }
3219
3220 return true;
3221}
3222
Geoff Langb1196682014-07-23 13:47:29 -04003223bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003224{
3225 if (program == 0)
3226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003227 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003228 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003229 }
3230
Jamie Madill43da7c42018-08-01 11:34:49 -04003231 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003232 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003233 {
3234 return false;
3235 }
3236
Jamie Madill0063c512014-08-25 15:47:53 -04003237 if (!programObject || !programObject->isLinked())
3238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003240 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003241 }
3242
Geoff Lang7dd2e102014-11-10 15:19:26 -05003243 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003245 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003246 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003247 }
3248
Jamie Madill0063c512014-08-25 15:47:53 -04003249 return true;
3250}
3251
Geoff Langf41d0ee2016-10-07 13:04:23 -04003252static bool ValidateSizedGetUniform(Context *context,
3253 GLuint program,
3254 GLint location,
3255 GLsizei bufSize,
3256 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003257{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003258 if (length)
3259 {
3260 *length = 0;
3261 }
3262
Jamie Madill78f41802014-08-25 15:47:55 -04003263 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003264 {
Jamie Madill78f41802014-08-25 15:47:55 -04003265 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003266 }
3267
Geoff Langf41d0ee2016-10-07 13:04:23 -04003268 if (bufSize < 0)
3269 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003270 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003271 return false;
3272 }
3273
Jamie Madill44a6fbf2018-10-02 13:38:56 -04003274 Program *programObject = context->getProgramResolveLink(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003275 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003276
Jamie Madill78f41802014-08-25 15:47:55 -04003277 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003278 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003279 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003280 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003281 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003282 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003283 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003284 }
3285
Geoff Langf41d0ee2016-10-07 13:04:23 -04003286 if (length)
3287 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003288 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003289 }
3290
Jamie Madill0063c512014-08-25 15:47:53 -04003291 return true;
3292}
3293
He Yunchaoced53ae2016-11-29 15:00:51 +08003294bool ValidateGetnUniformfvEXT(Context *context,
3295 GLuint program,
3296 GLint location,
3297 GLsizei bufSize,
3298 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003299{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003300 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003301}
3302
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003303bool ValidateGetnUniformfvRobustANGLE(Context *context,
3304 GLuint program,
3305 GLint location,
3306 GLsizei bufSize,
3307 GLsizei *length,
3308 GLfloat *params)
3309{
3310 UNIMPLEMENTED();
3311 return false;
3312}
3313
He Yunchaoced53ae2016-11-29 15:00:51 +08003314bool ValidateGetnUniformivEXT(Context *context,
3315 GLuint program,
3316 GLint location,
3317 GLsizei bufSize,
3318 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003319{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003320 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3321}
3322
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003323bool ValidateGetnUniformivRobustANGLE(Context *context,
3324 GLuint program,
3325 GLint location,
3326 GLsizei bufSize,
3327 GLsizei *length,
3328 GLint *params)
3329{
3330 UNIMPLEMENTED();
3331 return false;
3332}
3333
3334bool ValidateGetnUniformuivRobustANGLE(Context *context,
3335 GLuint program,
3336 GLint location,
3337 GLsizei bufSize,
3338 GLsizei *length,
3339 GLuint *params)
3340{
3341 UNIMPLEMENTED();
3342 return false;
3343}
3344
Geoff Langf41d0ee2016-10-07 13:04:23 -04003345bool ValidateGetUniformfvRobustANGLE(Context *context,
3346 GLuint program,
3347 GLint location,
3348 GLsizei bufSize,
3349 GLsizei *length,
3350 GLfloat *params)
3351{
3352 if (!ValidateRobustEntryPoint(context, bufSize))
3353 {
3354 return false;
3355 }
3356
Brandon Jonesd1049182018-03-28 10:02:20 -07003357 GLsizei writeLength = 0;
3358
Geoff Langf41d0ee2016-10-07 13:04:23 -04003359 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003360 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3361 {
3362 return false;
3363 }
3364
3365 SetRobustLengthParam(length, writeLength);
3366
3367 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003368}
3369
3370bool ValidateGetUniformivRobustANGLE(Context *context,
3371 GLuint program,
3372 GLint location,
3373 GLsizei bufSize,
3374 GLsizei *length,
3375 GLint *params)
3376{
3377 if (!ValidateRobustEntryPoint(context, bufSize))
3378 {
3379 return false;
3380 }
3381
Brandon Jonesd1049182018-03-28 10:02:20 -07003382 GLsizei writeLength = 0;
3383
Geoff Langf41d0ee2016-10-07 13:04:23 -04003384 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003385 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3386 {
3387 return false;
3388 }
3389
3390 SetRobustLengthParam(length, writeLength);
3391
3392 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003393}
3394
3395bool ValidateGetUniformuivRobustANGLE(Context *context,
3396 GLuint program,
3397 GLint location,
3398 GLsizei bufSize,
3399 GLsizei *length,
3400 GLuint *params)
3401{
3402 if (!ValidateRobustEntryPoint(context, bufSize))
3403 {
3404 return false;
3405 }
3406
3407 if (context->getClientMajorVersion() < 3)
3408 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003409 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003410 return false;
3411 }
3412
Brandon Jonesd1049182018-03-28 10:02:20 -07003413 GLsizei writeLength = 0;
3414
Geoff Langf41d0ee2016-10-07 13:04:23 -04003415 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003416 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3417 {
3418 return false;
3419 }
3420
3421 SetRobustLengthParam(length, writeLength);
3422
3423 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003424}
3425
He Yunchaoced53ae2016-11-29 15:00:51 +08003426bool ValidateDiscardFramebufferBase(Context *context,
3427 GLenum target,
3428 GLsizei numAttachments,
3429 const GLenum *attachments,
3430 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003431{
3432 if (numAttachments < 0)
3433 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003434 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003435 return false;
3436 }
3437
3438 for (GLsizei i = 0; i < numAttachments; ++i)
3439 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003440 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003441 {
3442 if (defaultFramebuffer)
3443 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003444 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003445 return false;
3446 }
3447
3448 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003450 context->handleError(InvalidOperation() << "Requested color attachment is "
3451 "greater than the maximum supported "
3452 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003453 return false;
3454 }
3455 }
3456 else
3457 {
3458 switch (attachments[i])
3459 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003460 case GL_DEPTH_ATTACHMENT:
3461 case GL_STENCIL_ATTACHMENT:
3462 case GL_DEPTH_STENCIL_ATTACHMENT:
3463 if (defaultFramebuffer)
3464 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003465 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3466 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003467 return false;
3468 }
3469 break;
3470 case GL_COLOR:
3471 case GL_DEPTH:
3472 case GL_STENCIL:
3473 if (!defaultFramebuffer)
3474 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003475 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3476 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003477 return false;
3478 }
3479 break;
3480 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003481 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003482 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003483 }
3484 }
3485 }
3486
3487 return true;
3488}
3489
Austin Kinross6ee1e782015-05-29 17:05:37 -07003490bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3491{
Jamie Madill007530e2017-12-28 14:27:04 -05003492 if (!context->getExtensions().debugMarker)
3493 {
3494 // The debug marker calls should not set error state
3495 // However, it seems reasonable to set an error state if the extension is not enabled
3496 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3497 return false;
3498 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003499
Jamie Madill007530e2017-12-28 14:27:04 -05003500 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003501 if (length < 0)
3502 {
3503 return false;
3504 }
3505
3506 if (marker == nullptr)
3507 {
3508 return false;
3509 }
3510
3511 return true;
3512}
3513
3514bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3515{
Jamie Madill007530e2017-12-28 14:27:04 -05003516 if (!context->getExtensions().debugMarker)
3517 {
3518 // The debug marker calls should not set error state
3519 // However, it seems reasonable to set an error state if the extension is not enabled
3520 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3521 return false;
3522 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003523
Jamie Madill007530e2017-12-28 14:27:04 -05003524 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003525 if (length < 0)
3526 {
3527 return false;
3528 }
3529
3530 if (length > 0 && marker == nullptr)
3531 {
3532 return false;
3533 }
3534
3535 return true;
3536}
3537
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003538bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003539{
Geoff Langa8406172015-07-21 16:53:39 -04003540 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003542 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003543 return false;
3544 }
3545
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003546 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003547 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003548 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003549 if (!context->getExtensions().eglImage)
3550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003551 context->handleError(InvalidEnum()
3552 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003553 }
3554 break;
3555
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003556 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003557 if (!context->getExtensions().eglImageExternal)
3558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003559 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3560 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003561 }
Geoff Langa8406172015-07-21 16:53:39 -04003562 break;
3563
3564 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003565 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003566 return false;
3567 }
3568
Rafael Cintron05a449a2018-06-20 18:08:04 -07003569 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003570
Jamie Madill61e16b42017-06-19 11:13:23 -04003571 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003572 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003574 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003575 return false;
3576 }
3577
Jamie Madill007530e2017-12-28 14:27:04 -05003578 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003580 context->handleError(InvalidOperation()
3581 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003582 return false;
3583 }
3584
Yuly Novikov2eb54072018-08-22 16:41:26 -04003585 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003587 context->handleError(InvalidOperation()
3588 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003589 return false;
3590 }
3591
Geoff Langdcab33b2015-07-21 13:03:16 -04003592 return true;
3593}
3594
3595bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003596 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003597 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003598{
Geoff Langa8406172015-07-21 16:53:39 -04003599 if (!context->getExtensions().eglImage)
3600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003601 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003602 return false;
3603 }
3604
3605 switch (target)
3606 {
3607 case GL_RENDERBUFFER:
3608 break;
3609
3610 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003611 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003612 return false;
3613 }
3614
Rafael Cintron05a449a2018-06-20 18:08:04 -07003615 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003616
Jamie Madill61e16b42017-06-19 11:13:23 -04003617 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003618 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003621 return false;
3622 }
3623
Yuly Novikov2eb54072018-08-22 16:41:26 -04003624 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003625 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003626 context->handleError(InvalidOperation()
3627 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003628 return false;
3629 }
3630
Geoff Langdcab33b2015-07-21 13:03:16 -04003631 return true;
3632}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003633
3634bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3635{
Geoff Lang36167ab2015-12-07 10:27:14 -05003636 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003637 {
3638 // The default VAO should always exist
3639 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003640 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003641 return false;
3642 }
3643
3644 return true;
3645}
3646
Geoff Langc5629752015-12-07 16:29:04 -05003647bool ValidateProgramBinaryBase(Context *context,
3648 GLuint program,
3649 GLenum binaryFormat,
3650 const void *binary,
3651 GLint length)
3652{
3653 Program *programObject = GetValidProgram(context, program);
3654 if (programObject == nullptr)
3655 {
3656 return false;
3657 }
3658
3659 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3660 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3661 programBinaryFormats.end())
3662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003663 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003664 return false;
3665 }
3666
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003667 if (context->hasActiveTransformFeedback(program))
3668 {
3669 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003670 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3671 "is associated with an active transform "
3672 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003673 return false;
3674 }
3675
Geoff Langc5629752015-12-07 16:29:04 -05003676 return true;
3677}
3678
3679bool ValidateGetProgramBinaryBase(Context *context,
3680 GLuint program,
3681 GLsizei bufSize,
3682 GLsizei *length,
3683 GLenum *binaryFormat,
3684 void *binary)
3685{
3686 Program *programObject = GetValidProgram(context, program);
3687 if (programObject == nullptr)
3688 {
3689 return false;
3690 }
3691
3692 if (!programObject->isLinked())
3693 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003694 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003695 return false;
3696 }
3697
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003698 if (context->getCaps().programBinaryFormats.empty())
3699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003700 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003701 return false;
3702 }
3703
Geoff Langc5629752015-12-07 16:29:04 -05003704 return true;
3705}
Jamie Madillc29968b2016-01-20 11:17:23 -05003706
Jamie Madill5b772312018-03-08 20:28:32 -05003707bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003708{
3709 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003710 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003711 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003712 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3713 return false;
3714 }
3715 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3716 {
3717 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003718 return false;
3719 }
3720
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003721 ASSERT(context->getGLState().getDrawFramebuffer());
3722 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003723 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3724
3725 // This should come first before the check for the default frame buffer
3726 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3727 // rather than INVALID_OPERATION
3728 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3729 {
3730 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3731
3732 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003733 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3734 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003735 {
3736 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003737 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3738 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3739 // 3.1 is still a bit ambiguous about the error, but future specs are
3740 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003741 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003742 return false;
3743 }
3744 else if (bufs[colorAttachment] >= maxColorAttachment)
3745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003746 context->handleError(InvalidOperation()
3747 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003748 return false;
3749 }
3750 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3751 frameBufferId != 0)
3752 {
3753 // INVALID_OPERATION-GL is bound to buffer and ith argument
3754 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003755 context->handleError(InvalidOperation()
3756 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003757 return false;
3758 }
3759 }
3760
3761 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3762 // and n is not 1 or bufs is bound to value other than BACK and NONE
3763 if (frameBufferId == 0)
3764 {
3765 if (n != 1)
3766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003767 context->handleError(InvalidOperation()
3768 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003769 return false;
3770 }
3771
3772 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003774 context->handleError(
3775 InvalidOperation()
3776 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003777 return false;
3778 }
3779 }
3780
3781 return true;
3782}
3783
Geoff Lang496c02d2016-10-20 11:38:11 -07003784bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003785 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003786 GLenum pname,
3787 GLsizei *length,
3788 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003789{
Geoff Lang496c02d2016-10-20 11:38:11 -07003790 if (length)
3791 {
3792 *length = 0;
3793 }
3794
3795 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3796 {
3797 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003798 InvalidOperation()
3799 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003800 return false;
3801 }
3802
Corentin Walleze4477002017-12-01 14:39:58 -05003803 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003804 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003805 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003806 return false;
3807 }
3808
Geoff Lang496c02d2016-10-20 11:38:11 -07003809 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003810 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003811 case GL_BUFFER_MAP_POINTER:
3812 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003813
Geoff Lang496c02d2016-10-20 11:38:11 -07003814 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003815 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003816 return false;
3817 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003818
3819 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3820 // target bound to zero generate an INVALID_OPERATION error."
3821 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003822 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003824 context->handleError(InvalidOperation()
3825 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003826 return false;
3827 }
3828
Geoff Lang496c02d2016-10-20 11:38:11 -07003829 if (length)
3830 {
3831 *length = 1;
3832 }
3833
Olli Etuaho4f667482016-03-30 15:56:35 +03003834 return true;
3835}
3836
Corentin Wallez336129f2017-10-17 15:55:40 -04003837bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003838{
Corentin Walleze4477002017-12-01 14:39:58 -05003839 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003840 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003841 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003842 return false;
3843 }
3844
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003845 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003846
3847 if (buffer == nullptr || !buffer->isMapped())
3848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003849 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003850 return false;
3851 }
3852
3853 return true;
3854}
3855
3856bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003857 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 GLintptr offset,
3859 GLsizeiptr length,
3860 GLbitfield access)
3861{
Corentin Walleze4477002017-12-01 14:39:58 -05003862 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003864 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003865 return false;
3866 }
3867
Brandon Jones6cad5662017-06-14 13:25:13 -07003868 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003869 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003870 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3871 return false;
3872 }
3873
3874 if (length < 0)
3875 {
3876 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003877 return false;
3878 }
3879
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003880 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003881
3882 if (!buffer)
3883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003884 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003885 return false;
3886 }
3887
3888 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003889 CheckedNumeric<size_t> checkedOffset(offset);
3890 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003891
Jamie Madille2e406c2016-06-02 13:04:10 -04003892 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003893 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003894 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003895 return false;
3896 }
3897
3898 // Check for invalid bits in the mask
3899 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3900 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3901 GL_MAP_UNSYNCHRONIZED_BIT;
3902
3903 if (access & ~(allAccessBits))
3904 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003905 context->handleError(InvalidValue()
3906 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003907 return false;
3908 }
3909
3910 if (length == 0)
3911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003912 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003913 return false;
3914 }
3915
3916 if (buffer->isMapped())
3917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003918 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003919 return false;
3920 }
3921
3922 // Check for invalid bit combinations
3923 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003925 context->handleError(InvalidOperation()
3926 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003927 return false;
3928 }
3929
3930 GLbitfield writeOnlyBits =
3931 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3932
3933 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003935 context->handleError(InvalidOperation()
3936 << "Invalid access bits when mapping buffer for reading: 0x"
3937 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003938 return false;
3939 }
3940
3941 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003943 context->handleError(
3944 InvalidOperation()
3945 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003946 return false;
3947 }
Geoff Lang79f71042017-08-14 16:43:43 -04003948
3949 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003950}
3951
3952bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003953 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003954 GLintptr offset,
3955 GLsizeiptr length)
3956{
Brandon Jones6cad5662017-06-14 13:25:13 -07003957 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003958 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003959 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3960 return false;
3961 }
3962
3963 if (length < 0)
3964 {
3965 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003966 return false;
3967 }
3968
Corentin Walleze4477002017-12-01 14:39:58 -05003969 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003970 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003971 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003972 return false;
3973 }
3974
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003975 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003976
3977 if (buffer == nullptr)
3978 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003979 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003980 return false;
3981 }
3982
3983 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3984 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003985 context->handleError(InvalidOperation()
3986 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003987 return false;
3988 }
3989
3990 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003991 CheckedNumeric<size_t> checkedOffset(offset);
3992 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003993
Jamie Madille2e406c2016-06-02 13:04:10 -04003994 if (!checkedSize.IsValid() ||
3995 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003997 context->handleError(InvalidValue()
3998 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003999 return false;
4000 }
4001
4002 return true;
4003}
4004
Olli Etuaho41997e72016-03-10 13:38:39 +02004005bool ValidateGenOrDelete(Context *context, GLint n)
4006{
4007 if (n < 0)
4008 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004009 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004010 return false;
4011 }
4012 return true;
4013}
4014
Jamie Madill5b772312018-03-08 20:28:32 -05004015bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004016{
4017 if (!context->getExtensions().robustClientMemory)
4018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004019 context->handleError(InvalidOperation()
4020 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004021 return false;
4022 }
4023
4024 if (bufSize < 0)
4025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004026 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004027 return false;
4028 }
4029
4030 return true;
4031}
4032
Jamie Madill5b772312018-03-08 20:28:32 -05004033bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004034{
4035 if (bufSize < numParams)
4036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004037 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4038 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004039 return false;
4040 }
4041
4042 return true;
4043}
4044
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004045bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004046 GLenum target,
4047 GLenum attachment,
4048 GLenum pname,
4049 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004050{
Geoff Lange8afa902017-09-27 15:00:43 -04004051 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004052 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004053 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004054 return false;
4055 }
4056
4057 int clientVersion = context->getClientMajorVersion();
4058
4059 switch (pname)
4060 {
4061 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4062 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4063 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4064 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4065 break;
4066
Martin Radeve5285d22017-07-14 16:23:53 +03004067 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4068 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4069 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4070 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4071 if (clientVersion < 3 || !context->getExtensions().multiview)
4072 {
4073 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4074 return false;
4075 }
4076 break;
4077
Geoff Langff5b2d52016-09-07 11:32:23 -04004078 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4079 if (clientVersion < 3 && !context->getExtensions().sRGB)
4080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004081 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004082 return false;
4083 }
4084 break;
4085
4086 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4087 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4088 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4089 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4090 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4091 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4092 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4093 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4094 if (clientVersion < 3)
4095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004096 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 return false;
4098 }
4099 break;
4100
Jiawei Shaoa8802472018-05-28 11:17:47 +08004101 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4102 if (!context->getExtensions().geometryShader)
4103 {
4104 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4105 return false;
4106 }
4107 break;
4108
Geoff Langff5b2d52016-09-07 11:32:23 -04004109 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004110 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004111 return false;
4112 }
4113
4114 // Determine if the attachment is a valid enum
4115 switch (attachment)
4116 {
4117 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004118 case GL_DEPTH:
4119 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004120 if (clientVersion < 3)
4121 {
Geoff Langfa125c92017-10-24 13:01:46 -04004122 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004123 return false;
4124 }
4125 break;
4126
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004127 case GL_DEPTH_STENCIL_ATTACHMENT:
4128 if (clientVersion < 3 && !context->isWebGL1())
4129 {
4130 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4131 return false;
4132 }
4133 break;
4134
Geoff Langfa125c92017-10-24 13:01:46 -04004135 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004136 case GL_DEPTH_ATTACHMENT:
4137 case GL_STENCIL_ATTACHMENT:
4138 break;
4139
4140 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004141 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4142 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004143 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4144 {
Geoff Langfa125c92017-10-24 13:01:46 -04004145 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 return false;
4147 }
4148 break;
4149 }
4150
4151 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4152 ASSERT(framebuffer);
4153
4154 if (framebuffer->id() == 0)
4155 {
4156 if (clientVersion < 3)
4157 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004158 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 return false;
4160 }
4161
4162 switch (attachment)
4163 {
4164 case GL_BACK:
4165 case GL_DEPTH:
4166 case GL_STENCIL:
4167 break;
4168
4169 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004171 return false;
4172 }
4173 }
4174 else
4175 {
4176 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4177 {
4178 // Valid attachment query
4179 }
4180 else
4181 {
4182 switch (attachment)
4183 {
4184 case GL_DEPTH_ATTACHMENT:
4185 case GL_STENCIL_ATTACHMENT:
4186 break;
4187
4188 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004189 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004191 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004192 return false;
4193 }
4194 break;
4195
4196 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004197 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004198 return false;
4199 }
4200 }
4201 }
4202
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004203 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004204 if (attachmentObject)
4205 {
4206 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4207 attachmentObject->type() == GL_TEXTURE ||
4208 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4209
4210 switch (pname)
4211 {
4212 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4213 if (attachmentObject->type() != GL_RENDERBUFFER &&
4214 attachmentObject->type() != GL_TEXTURE)
4215 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004216 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004217 return false;
4218 }
4219 break;
4220
4221 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4222 if (attachmentObject->type() != GL_TEXTURE)
4223 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004224 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004225 return false;
4226 }
4227 break;
4228
4229 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4230 if (attachmentObject->type() != GL_TEXTURE)
4231 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004233 return false;
4234 }
4235 break;
4236
4237 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4238 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4239 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004240 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004241 return false;
4242 }
4243 break;
4244
4245 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4246 if (attachmentObject->type() != GL_TEXTURE)
4247 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004248 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004249 return false;
4250 }
4251 break;
4252
4253 default:
4254 break;
4255 }
4256 }
4257 else
4258 {
4259 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4260 // is NONE, then querying any other pname will generate INVALID_ENUM.
4261
4262 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4263 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4264 // INVALID_OPERATION for all other pnames
4265
4266 switch (pname)
4267 {
4268 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4269 break;
4270
4271 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4272 if (clientVersion < 3)
4273 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004274 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004275 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004276 return false;
4277 }
4278 break;
4279
4280 default:
4281 if (clientVersion < 3)
4282 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004283 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004284 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004285 return false;
4286 }
4287 else
4288 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004289 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004290 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004291 return false;
4292 }
4293 }
4294 }
4295
Martin Radeve5285d22017-07-14 16:23:53 +03004296 if (numParams)
4297 {
4298 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4299 {
4300 // Only when the viewport offsets are queried we can have a varying number of output
4301 // parameters.
4302 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4303 *numParams = numViews * 2;
4304 }
4305 else
4306 {
4307 // For all other queries we can have only one output parameter.
4308 *numParams = 1;
4309 }
4310 }
4311
Geoff Langff5b2d52016-09-07 11:32:23 -04004312 return true;
4313}
4314
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004315bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004316 GLenum target,
4317 GLenum attachment,
4318 GLenum pname,
4319 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004320 GLsizei *length,
4321 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004322{
4323 if (!ValidateRobustEntryPoint(context, bufSize))
4324 {
4325 return false;
4326 }
4327
Brandon Jonesd1049182018-03-28 10:02:20 -07004328 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004329 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004330 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004331 {
4332 return false;
4333 }
4334
Brandon Jonesd1049182018-03-28 10:02:20 -07004335 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004336 {
4337 return false;
4338 }
4339
Brandon Jonesd1049182018-03-28 10:02:20 -07004340 SetRobustLengthParam(length, numParams);
4341
Geoff Langff5b2d52016-09-07 11:32:23 -04004342 return true;
4343}
4344
Jamie Madill5b772312018-03-08 20:28:32 -05004345bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004346 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004347 GLenum pname,
4348 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004349 GLsizei *length,
4350 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004351{
4352 if (!ValidateRobustEntryPoint(context, bufSize))
4353 {
4354 return false;
4355 }
4356
Brandon Jonesd1049182018-03-28 10:02:20 -07004357 GLsizei numParams = 0;
4358
4359 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004360 {
4361 return false;
4362 }
4363
Brandon Jonesd1049182018-03-28 10:02:20 -07004364 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004365 {
4366 return false;
4367 }
4368
Brandon Jonesd1049182018-03-28 10:02:20 -07004369 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004370 return true;
4371}
4372
Jamie Madill5b772312018-03-08 20:28:32 -05004373bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004374 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004375 GLenum pname,
4376 GLsizei bufSize,
4377 GLsizei *length,
4378 GLint64 *params)
4379{
Brandon Jonesd1049182018-03-28 10:02:20 -07004380 GLsizei numParams = 0;
4381
Geoff Langebebe1c2016-10-14 12:01:31 -04004382 if (!ValidateRobustEntryPoint(context, bufSize))
4383 {
4384 return false;
4385 }
4386
Brandon Jonesd1049182018-03-28 10:02:20 -07004387 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004388 {
4389 return false;
4390 }
4391
Brandon Jonesd1049182018-03-28 10:02:20 -07004392 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004393 {
4394 return false;
4395 }
4396
Brandon Jonesd1049182018-03-28 10:02:20 -07004397 SetRobustLengthParam(length, numParams);
4398
Geoff Langff5b2d52016-09-07 11:32:23 -04004399 return true;
4400}
4401
Jamie Madill5b772312018-03-08 20:28:32 -05004402bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004403{
4404 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004405 if (numParams)
4406 {
4407 *numParams = 1;
4408 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004409
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004410 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
4411 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
4412 ? GetValidProgramNoResolve(context, program)
4413 : GetValidProgram(context, program);
Geoff Langff5b2d52016-09-07 11:32:23 -04004414 if (!programObject)
4415 {
4416 return false;
4417 }
4418
4419 switch (pname)
4420 {
4421 case GL_DELETE_STATUS:
4422 case GL_LINK_STATUS:
4423 case GL_VALIDATE_STATUS:
4424 case GL_INFO_LOG_LENGTH:
4425 case GL_ATTACHED_SHADERS:
4426 case GL_ACTIVE_ATTRIBUTES:
4427 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4428 case GL_ACTIVE_UNIFORMS:
4429 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4430 break;
4431
4432 case GL_PROGRAM_BINARY_LENGTH:
4433 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004435 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4436 "requires GL_OES_get_program_binary or "
4437 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004438 return false;
4439 }
4440 break;
4441
4442 case GL_ACTIVE_UNIFORM_BLOCKS:
4443 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4444 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4445 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4446 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4447 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4448 if (context->getClientMajorVersion() < 3)
4449 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004450 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004451 return false;
4452 }
4453 break;
4454
Yunchao He61afff12017-03-14 15:34:03 +08004455 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004456 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004457 if (context->getClientVersion() < Version(3, 1))
4458 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004459 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004460 return false;
4461 }
4462 break;
4463
Jiawei Shao6ae51612018-02-23 14:03:25 +08004464 case GL_COMPUTE_WORK_GROUP_SIZE:
4465 if (context->getClientVersion() < Version(3, 1))
4466 {
4467 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4468 return false;
4469 }
4470
4471 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4472 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4473 // program which has not been linked successfully, or which does not contain objects to
4474 // form a compute shader.
4475 if (!programObject->isLinked())
4476 {
4477 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4478 return false;
4479 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004480 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004481 {
4482 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4483 return false;
4484 }
4485 break;
4486
Jiawei Shao447bfac2018-03-14 14:23:40 +08004487 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4488 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4489 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4490 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4491 if (!context->getExtensions().geometryShader)
4492 {
4493 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4494 return false;
4495 }
4496
4497 // [EXT_geometry_shader] Chapter 7.12
4498 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4499 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4500 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4501 // successfully, or which does not contain objects to form a geometry shader.
4502 if (!programObject->isLinked())
4503 {
4504 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4505 return false;
4506 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004507 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004508 {
4509 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4510 return false;
4511 }
4512 break;
4513
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004514 case GL_COMPLETION_STATUS_KHR:
4515 if (!context->getExtensions().parallelShaderCompile)
4516 {
4517 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
4518 return false;
4519 }
4520 break;
4521
Geoff Langff5b2d52016-09-07 11:32:23 -04004522 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004524 return false;
4525 }
4526
4527 return true;
4528}
4529
4530bool ValidateGetProgramivRobustANGLE(Context *context,
4531 GLuint program,
4532 GLenum pname,
4533 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004534 GLsizei *length,
4535 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004536{
4537 if (!ValidateRobustEntryPoint(context, bufSize))
4538 {
4539 return false;
4540 }
4541
Brandon Jonesd1049182018-03-28 10:02:20 -07004542 GLsizei numParams = 0;
4543
4544 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004545 {
4546 return false;
4547 }
4548
Brandon Jonesd1049182018-03-28 10:02:20 -07004549 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004550 {
4551 return false;
4552 }
4553
Brandon Jonesd1049182018-03-28 10:02:20 -07004554 SetRobustLengthParam(length, numParams);
4555
Geoff Langff5b2d52016-09-07 11:32:23 -04004556 return true;
4557}
4558
Geoff Lang740d9022016-10-07 11:20:52 -04004559bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4560 GLenum target,
4561 GLenum pname,
4562 GLsizei bufSize,
4563 GLsizei *length,
4564 GLint *params)
4565{
4566 if (!ValidateRobustEntryPoint(context, bufSize))
4567 {
4568 return false;
4569 }
4570
Brandon Jonesd1049182018-03-28 10:02:20 -07004571 GLsizei numParams = 0;
4572
4573 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004574 {
4575 return false;
4576 }
4577
Brandon Jonesd1049182018-03-28 10:02:20 -07004578 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004579 {
4580 return false;
4581 }
4582
Brandon Jonesd1049182018-03-28 10:02:20 -07004583 SetRobustLengthParam(length, numParams);
4584
Geoff Lang740d9022016-10-07 11:20:52 -04004585 return true;
4586}
4587
Geoff Langd7d0ed32016-10-07 11:33:51 -04004588bool ValidateGetShaderivRobustANGLE(Context *context,
4589 GLuint shader,
4590 GLenum pname,
4591 GLsizei bufSize,
4592 GLsizei *length,
4593 GLint *params)
4594{
4595 if (!ValidateRobustEntryPoint(context, bufSize))
4596 {
4597 return false;
4598 }
4599
Brandon Jonesd1049182018-03-28 10:02:20 -07004600 GLsizei numParams = 0;
4601
4602 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004603 {
4604 return false;
4605 }
4606
Brandon Jonesd1049182018-03-28 10:02:20 -07004607 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004608 {
4609 return false;
4610 }
4611
Brandon Jonesd1049182018-03-28 10:02:20 -07004612 SetRobustLengthParam(length, numParams);
4613
Geoff Langd7d0ed32016-10-07 11:33:51 -04004614 return true;
4615}
4616
Geoff Langc1984ed2016-10-07 12:41:00 -04004617bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004618 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004619 GLenum pname,
4620 GLsizei bufSize,
4621 GLsizei *length,
4622 GLfloat *params)
4623{
4624 if (!ValidateRobustEntryPoint(context, bufSize))
4625 {
4626 return false;
4627 }
4628
Brandon Jonesd1049182018-03-28 10:02:20 -07004629 GLsizei numParams = 0;
4630
4631 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004632 {
4633 return false;
4634 }
4635
Brandon Jonesd1049182018-03-28 10:02:20 -07004636 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004637 {
4638 return false;
4639 }
4640
Brandon Jonesd1049182018-03-28 10:02:20 -07004641 SetRobustLengthParam(length, numParams);
4642
Geoff Langc1984ed2016-10-07 12:41:00 -04004643 return true;
4644}
4645
Geoff Langc1984ed2016-10-07 12:41:00 -04004646bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004647 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004648 GLenum pname,
4649 GLsizei bufSize,
4650 GLsizei *length,
4651 GLint *params)
4652{
Brandon Jonesd1049182018-03-28 10:02:20 -07004653
Geoff Langc1984ed2016-10-07 12:41:00 -04004654 if (!ValidateRobustEntryPoint(context, bufSize))
4655 {
4656 return false;
4657 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004658 GLsizei numParams = 0;
4659 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004660 {
4661 return false;
4662 }
4663
Brandon Jonesd1049182018-03-28 10:02:20 -07004664 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004665 {
4666 return false;
4667 }
4668
Brandon Jonesd1049182018-03-28 10:02:20 -07004669 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004670 return true;
4671}
4672
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004673bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4674 TextureType target,
4675 GLenum pname,
4676 GLsizei bufSize,
4677 GLsizei *length,
4678 GLint *params)
4679{
4680 UNIMPLEMENTED();
4681 return false;
4682}
4683
4684bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4685 TextureType target,
4686 GLenum pname,
4687 GLsizei bufSize,
4688 GLsizei *length,
4689 GLuint *params)
4690{
4691 UNIMPLEMENTED();
4692 return false;
4693}
4694
Geoff Langc1984ed2016-10-07 12:41:00 -04004695bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004696 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004697 GLenum pname,
4698 GLsizei bufSize,
4699 const GLfloat *params)
4700{
4701 if (!ValidateRobustEntryPoint(context, bufSize))
4702 {
4703 return false;
4704 }
4705
4706 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4707}
4708
Geoff Langc1984ed2016-10-07 12:41:00 -04004709bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004710 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004711 GLenum pname,
4712 GLsizei bufSize,
4713 const GLint *params)
4714{
4715 if (!ValidateRobustEntryPoint(context, bufSize))
4716 {
4717 return false;
4718 }
4719
4720 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4721}
4722
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004723bool ValidateTexParameterIivRobustANGLE(Context *context,
4724 TextureType target,
4725 GLenum pname,
4726 GLsizei bufSize,
4727 const GLint *params)
4728{
4729 UNIMPLEMENTED();
4730 return false;
4731}
4732
4733bool ValidateTexParameterIuivRobustANGLE(Context *context,
4734 TextureType target,
4735 GLenum pname,
4736 GLsizei bufSize,
4737 const GLuint *params)
4738{
4739 UNIMPLEMENTED();
4740 return false;
4741}
4742
Geoff Langc1984ed2016-10-07 12:41:00 -04004743bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4744 GLuint sampler,
4745 GLenum pname,
4746 GLuint bufSize,
4747 GLsizei *length,
4748 GLfloat *params)
4749{
4750 if (!ValidateRobustEntryPoint(context, bufSize))
4751 {
4752 return false;
4753 }
4754
Brandon Jonesd1049182018-03-28 10:02:20 -07004755 GLsizei numParams = 0;
4756
4757 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004758 {
4759 return false;
4760 }
4761
Brandon Jonesd1049182018-03-28 10:02:20 -07004762 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004763 {
4764 return false;
4765 }
4766
Brandon Jonesd1049182018-03-28 10:02:20 -07004767 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004768 return true;
4769}
4770
Geoff Langc1984ed2016-10-07 12:41:00 -04004771bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4772 GLuint sampler,
4773 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004774 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004775 GLsizei *length,
4776 GLint *params)
4777{
4778 if (!ValidateRobustEntryPoint(context, bufSize))
4779 {
4780 return false;
4781 }
4782
Brandon Jonesd1049182018-03-28 10:02:20 -07004783 GLsizei numParams = 0;
4784
4785 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004786 {
4787 return false;
4788 }
4789
Brandon Jonesd1049182018-03-28 10:02:20 -07004790 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004791 {
4792 return false;
4793 }
4794
Brandon Jonesd1049182018-03-28 10:02:20 -07004795 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004796 return true;
4797}
4798
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004799bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4800 GLuint sampler,
4801 GLenum pname,
4802 GLsizei bufSize,
4803 GLsizei *length,
4804 GLint *params)
4805{
4806 UNIMPLEMENTED();
4807 return false;
4808}
4809
4810bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4811 GLuint sampler,
4812 GLenum pname,
4813 GLsizei bufSize,
4814 GLsizei *length,
4815 GLuint *params)
4816{
4817 UNIMPLEMENTED();
4818 return false;
4819}
4820
Geoff Langc1984ed2016-10-07 12:41:00 -04004821bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4822 GLuint sampler,
4823 GLenum pname,
4824 GLsizei bufSize,
4825 const GLfloat *params)
4826{
4827 if (!ValidateRobustEntryPoint(context, bufSize))
4828 {
4829 return false;
4830 }
4831
4832 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4833}
4834
Geoff Langc1984ed2016-10-07 12:41:00 -04004835bool ValidateSamplerParameterivRobustANGLE(Context *context,
4836 GLuint sampler,
4837 GLenum pname,
4838 GLsizei bufSize,
4839 const GLint *params)
4840{
4841 if (!ValidateRobustEntryPoint(context, bufSize))
4842 {
4843 return false;
4844 }
4845
4846 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4847}
4848
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004849bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4850 GLuint sampler,
4851 GLenum pname,
4852 GLsizei bufSize,
4853 const GLint *param)
4854{
4855 UNIMPLEMENTED();
4856 return false;
4857}
4858
4859bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4860 GLuint sampler,
4861 GLenum pname,
4862 GLsizei bufSize,
4863 const GLuint *param)
4864{
4865 UNIMPLEMENTED();
4866 return false;
4867}
4868
Geoff Lang0b031062016-10-13 14:30:04 -04004869bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4870 GLuint index,
4871 GLenum pname,
4872 GLsizei bufSize,
4873 GLsizei *length,
4874 GLfloat *params)
4875{
4876 if (!ValidateRobustEntryPoint(context, bufSize))
4877 {
4878 return false;
4879 }
4880
Brandon Jonesd1049182018-03-28 10:02:20 -07004881 GLsizei writeLength = 0;
4882
4883 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004884 {
4885 return false;
4886 }
4887
Brandon Jonesd1049182018-03-28 10:02:20 -07004888 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004889 {
4890 return false;
4891 }
4892
Brandon Jonesd1049182018-03-28 10:02:20 -07004893 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004894 return true;
4895}
4896
Geoff Lang0b031062016-10-13 14:30:04 -04004897bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4898 GLuint index,
4899 GLenum pname,
4900 GLsizei bufSize,
4901 GLsizei *length,
4902 GLint *params)
4903{
4904 if (!ValidateRobustEntryPoint(context, bufSize))
4905 {
4906 return false;
4907 }
4908
Brandon Jonesd1049182018-03-28 10:02:20 -07004909 GLsizei writeLength = 0;
4910
4911 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004912 {
4913 return false;
4914 }
4915
Brandon Jonesd1049182018-03-28 10:02:20 -07004916 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004917 {
4918 return false;
4919 }
4920
Brandon Jonesd1049182018-03-28 10:02:20 -07004921 SetRobustLengthParam(length, writeLength);
4922
Geoff Lang0b031062016-10-13 14:30:04 -04004923 return true;
4924}
4925
Geoff Lang0b031062016-10-13 14:30:04 -04004926bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4927 GLuint index,
4928 GLenum pname,
4929 GLsizei bufSize,
4930 GLsizei *length,
4931 void **pointer)
4932{
4933 if (!ValidateRobustEntryPoint(context, bufSize))
4934 {
4935 return false;
4936 }
4937
Brandon Jonesd1049182018-03-28 10:02:20 -07004938 GLsizei writeLength = 0;
4939
4940 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004941 {
4942 return false;
4943 }
4944
Brandon Jonesd1049182018-03-28 10:02:20 -07004945 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004946 {
4947 return false;
4948 }
4949
Brandon Jonesd1049182018-03-28 10:02:20 -07004950 SetRobustLengthParam(length, writeLength);
4951
Geoff Lang0b031062016-10-13 14:30:04 -04004952 return true;
4953}
4954
Geoff Lang0b031062016-10-13 14:30:04 -04004955bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4956 GLuint index,
4957 GLenum pname,
4958 GLsizei bufSize,
4959 GLsizei *length,
4960 GLint *params)
4961{
4962 if (!ValidateRobustEntryPoint(context, bufSize))
4963 {
4964 return false;
4965 }
4966
Brandon Jonesd1049182018-03-28 10:02:20 -07004967 GLsizei writeLength = 0;
4968
4969 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004970 {
4971 return false;
4972 }
4973
Brandon Jonesd1049182018-03-28 10:02:20 -07004974 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004975 {
4976 return false;
4977 }
4978
Brandon Jonesd1049182018-03-28 10:02:20 -07004979 SetRobustLengthParam(length, writeLength);
4980
Geoff Lang0b031062016-10-13 14:30:04 -04004981 return true;
4982}
4983
Geoff Lang0b031062016-10-13 14:30:04 -04004984bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4985 GLuint index,
4986 GLenum pname,
4987 GLsizei bufSize,
4988 GLsizei *length,
4989 GLuint *params)
4990{
4991 if (!ValidateRobustEntryPoint(context, bufSize))
4992 {
4993 return false;
4994 }
4995
Brandon Jonesd1049182018-03-28 10:02:20 -07004996 GLsizei writeLength = 0;
4997
4998 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004999 {
5000 return false;
5001 }
5002
Brandon Jonesd1049182018-03-28 10:02:20 -07005003 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005004 {
5005 return false;
5006 }
5007
Brandon Jonesd1049182018-03-28 10:02:20 -07005008 SetRobustLengthParam(length, writeLength);
5009
Geoff Lang0b031062016-10-13 14:30:04 -04005010 return true;
5011}
5012
Geoff Lang6899b872016-10-14 11:30:13 -04005013bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5014 GLuint program,
5015 GLuint uniformBlockIndex,
5016 GLenum pname,
5017 GLsizei bufSize,
5018 GLsizei *length,
5019 GLint *params)
5020{
5021 if (!ValidateRobustEntryPoint(context, bufSize))
5022 {
5023 return false;
5024 }
5025
Brandon Jonesd1049182018-03-28 10:02:20 -07005026 GLsizei writeLength = 0;
5027
5028 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5029 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005030 {
5031 return false;
5032 }
5033
Brandon Jonesd1049182018-03-28 10:02:20 -07005034 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005035 {
5036 return false;
5037 }
5038
Brandon Jonesd1049182018-03-28 10:02:20 -07005039 SetRobustLengthParam(length, writeLength);
5040
Geoff Lang6899b872016-10-14 11:30:13 -04005041 return true;
5042}
5043
Brandon Jones416aaf92018-04-10 08:10:16 -07005044bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005045 GLenum target,
5046 GLenum internalformat,
5047 GLenum pname,
5048 GLsizei bufSize,
5049 GLsizei *length,
5050 GLint *params)
5051{
5052 if (!ValidateRobustEntryPoint(context, bufSize))
5053 {
5054 return false;
5055 }
5056
Brandon Jonesd1049182018-03-28 10:02:20 -07005057 GLsizei numParams = 0;
5058
5059 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5060 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005061 {
5062 return false;
5063 }
5064
Brandon Jonesd1049182018-03-28 10:02:20 -07005065 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005066 {
5067 return false;
5068 }
5069
Brandon Jonesd1049182018-03-28 10:02:20 -07005070 SetRobustLengthParam(length, numParams);
5071
Geoff Lang0a9661f2016-10-20 10:59:20 -07005072 return true;
5073}
5074
Jamie Madill5b772312018-03-08 20:28:32 -05005075bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005076 GLuint attribIndex,
5077 GLint size,
5078 GLenum type,
5079 GLboolean pureInteger)
5080{
5081 const Caps &caps = context->getCaps();
5082 if (attribIndex >= caps.maxVertexAttributes)
5083 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005084 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005085 return false;
5086 }
5087
5088 if (size < 1 || size > 4)
5089 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005090 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005091 return false;
Shao80957d92017-02-20 21:25:59 +08005092 }
5093
5094 switch (type)
5095 {
5096 case GL_BYTE:
5097 case GL_UNSIGNED_BYTE:
5098 case GL_SHORT:
5099 case GL_UNSIGNED_SHORT:
5100 break;
5101
5102 case GL_INT:
5103 case GL_UNSIGNED_INT:
5104 if (context->getClientMajorVersion() < 3)
5105 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005106 context->handleError(InvalidEnum()
5107 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005108 return false;
5109 }
5110 break;
5111
5112 case GL_FIXED:
5113 case GL_FLOAT:
5114 if (pureInteger)
5115 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005116 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005117 return false;
5118 }
5119 break;
5120
5121 case GL_HALF_FLOAT:
5122 if (context->getClientMajorVersion() < 3)
5123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005124 context->handleError(InvalidEnum()
5125 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005126 return false;
5127 }
5128 if (pureInteger)
5129 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005130 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005131 return false;
5132 }
5133 break;
5134
5135 case GL_INT_2_10_10_10_REV:
5136 case GL_UNSIGNED_INT_2_10_10_10_REV:
5137 if (context->getClientMajorVersion() < 3)
5138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005139 context->handleError(InvalidEnum()
5140 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005141 return false;
5142 }
5143 if (pureInteger)
5144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005145 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005146 return false;
5147 }
5148 if (size != 4)
5149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005150 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5151 "UNSIGNED_INT_2_10_10_10_REV and "
5152 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005153 return false;
5154 }
5155 break;
5156
5157 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005159 return false;
5160 }
5161
5162 return true;
5163}
5164
Geoff Lang76e65652017-03-27 14:58:02 -04005165// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5166// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5167// specified clear value and the type of a buffer that is being cleared generates an
5168// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005169bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005170 GLint drawbuffer,
5171 const GLenum *validComponentTypes,
5172 size_t validComponentTypeCount)
5173{
5174 const FramebufferAttachment *attachment =
5175 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5176 if (attachment)
5177 {
5178 GLenum componentType = attachment->getFormat().info->componentType;
5179 const GLenum *end = validComponentTypes + validComponentTypeCount;
5180 if (std::find(validComponentTypes, end, componentType) == end)
5181 {
5182 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005183 InvalidOperation()
5184 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005185 return false;
5186 }
5187 }
5188
5189 return true;
5190}
5191
Jamie Madill5b772312018-03-08 20:28:32 -05005192bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005193{
5194 if (!ValidateRobustEntryPoint(context, dataSize))
5195 {
5196 return false;
5197 }
5198
Jamie Madill43da7c42018-08-01 11:34:49 -04005199 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005200 if (pixelUnpackBuffer == nullptr)
5201 {
5202 if (dataSize < imageSize)
5203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005204 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005205 }
5206 }
5207 return true;
5208}
5209
Jamie Madill5b772312018-03-08 20:28:32 -05005210bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005211 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005212 GLenum pname,
5213 bool pointerVersion,
5214 GLsizei *numParams)
5215{
5216 if (numParams)
5217 {
5218 *numParams = 0;
5219 }
5220
Corentin Walleze4477002017-12-01 14:39:58 -05005221 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005223 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005224 return false;
5225 }
5226
5227 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5228 if (!buffer)
5229 {
5230 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005231 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005232 return false;
5233 }
5234
5235 const Extensions &extensions = context->getExtensions();
5236
5237 switch (pname)
5238 {
5239 case GL_BUFFER_USAGE:
5240 case GL_BUFFER_SIZE:
5241 break;
5242
5243 case GL_BUFFER_ACCESS_OES:
5244 if (!extensions.mapBuffer)
5245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005246 context->handleError(InvalidEnum()
5247 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005248 return false;
5249 }
5250 break;
5251
5252 case GL_BUFFER_MAPPED:
5253 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5254 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5255 !extensions.mapBufferRange)
5256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005257 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5258 "GL_OES_mapbuffer or "
5259 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005260 return false;
5261 }
5262 break;
5263
5264 case GL_BUFFER_MAP_POINTER:
5265 if (!pointerVersion)
5266 {
5267 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005268 InvalidEnum()
5269 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272 break;
5273
5274 case GL_BUFFER_ACCESS_FLAGS:
5275 case GL_BUFFER_MAP_OFFSET:
5276 case GL_BUFFER_MAP_LENGTH:
5277 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005279 context->handleError(InvalidEnum()
5280 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005281 return false;
5282 }
5283 break;
5284
Geoff Lang79b91402018-10-04 15:11:30 -04005285 case GL_MEMORY_SIZE_ANGLE:
5286 if (!context->getExtensions().memorySize)
5287 {
5288 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
5289 return false;
5290 }
5291 break;
5292
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005294 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005295 return false;
5296 }
5297
5298 // All buffer parameter queries return one value.
5299 if (numParams)
5300 {
5301 *numParams = 1;
5302 }
5303
5304 return true;
5305}
5306
5307bool ValidateGetRenderbufferParameterivBase(Context *context,
5308 GLenum target,
5309 GLenum pname,
5310 GLsizei *length)
5311{
5312 if (length)
5313 {
5314 *length = 0;
5315 }
5316
5317 if (target != GL_RENDERBUFFER)
5318 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005319 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005320 return false;
5321 }
5322
5323 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5324 if (renderbuffer == nullptr)
5325 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005326 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005327 return false;
5328 }
5329
5330 switch (pname)
5331 {
5332 case GL_RENDERBUFFER_WIDTH:
5333 case GL_RENDERBUFFER_HEIGHT:
5334 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5335 case GL_RENDERBUFFER_RED_SIZE:
5336 case GL_RENDERBUFFER_GREEN_SIZE:
5337 case GL_RENDERBUFFER_BLUE_SIZE:
5338 case GL_RENDERBUFFER_ALPHA_SIZE:
5339 case GL_RENDERBUFFER_DEPTH_SIZE:
5340 case GL_RENDERBUFFER_STENCIL_SIZE:
5341 break;
5342
5343 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5344 if (!context->getExtensions().framebufferMultisample)
5345 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005346 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 return false;
5348 }
5349 break;
5350
Geoff Lang79b91402018-10-04 15:11:30 -04005351 case GL_MEMORY_SIZE_ANGLE:
5352 if (!context->getExtensions().memorySize)
5353 {
5354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
5355 return false;
5356 }
5357 break;
5358
Jamie Madillbe849e42017-05-02 15:49:00 -04005359 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 return false;
5362 }
5363
5364 if (length)
5365 {
5366 *length = 1;
5367 }
5368 return true;
5369}
5370
5371bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5372{
5373 if (length)
5374 {
5375 *length = 0;
5376 }
5377
5378 if (GetValidShader(context, shader) == nullptr)
5379 {
5380 return false;
5381 }
5382
5383 switch (pname)
5384 {
5385 case GL_SHADER_TYPE:
5386 case GL_DELETE_STATUS:
5387 case GL_COMPILE_STATUS:
5388 case GL_INFO_LOG_LENGTH:
5389 case GL_SHADER_SOURCE_LENGTH:
5390 break;
5391
5392 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5393 if (!context->getExtensions().translatedShaderSource)
5394 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005395 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005396 return false;
5397 }
5398 break;
5399
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005400 case GL_COMPLETION_STATUS_KHR:
5401 if (!context->getExtensions().parallelShaderCompile)
5402 {
5403 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
5404 return false;
5405 }
5406 break;
5407
Jamie Madillbe849e42017-05-02 15:49:00 -04005408 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005409 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005410 return false;
5411 }
5412
5413 if (length)
5414 {
5415 *length = 1;
5416 }
5417 return true;
5418}
5419
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005420bool ValidateGetTexParameterBase(Context *context,
5421 TextureType target,
5422 GLenum pname,
5423 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005424{
5425 if (length)
5426 {
5427 *length = 0;
5428 }
5429
5430 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5431 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005433 return false;
5434 }
5435
5436 if (context->getTargetTexture(target) == nullptr)
5437 {
5438 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005439 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005440 return false;
5441 }
5442
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005443 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5444 {
5445 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5446 return false;
5447 }
5448
Jamie Madillbe849e42017-05-02 15:49:00 -04005449 switch (pname)
5450 {
5451 case GL_TEXTURE_MAG_FILTER:
5452 case GL_TEXTURE_MIN_FILTER:
5453 case GL_TEXTURE_WRAP_S:
5454 case GL_TEXTURE_WRAP_T:
5455 break;
5456
5457 case GL_TEXTURE_USAGE_ANGLE:
5458 if (!context->getExtensions().textureUsage)
5459 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005460 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005461 return false;
5462 }
5463 break;
5464
5465 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005466 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005468 return false;
5469 }
5470 break;
5471
5472 case GL_TEXTURE_IMMUTABLE_FORMAT:
5473 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5474 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005475 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005476 return false;
5477 }
5478 break;
5479
5480 case GL_TEXTURE_WRAP_R:
5481 case GL_TEXTURE_IMMUTABLE_LEVELS:
5482 case GL_TEXTURE_SWIZZLE_R:
5483 case GL_TEXTURE_SWIZZLE_G:
5484 case GL_TEXTURE_SWIZZLE_B:
5485 case GL_TEXTURE_SWIZZLE_A:
5486 case GL_TEXTURE_BASE_LEVEL:
5487 case GL_TEXTURE_MAX_LEVEL:
5488 case GL_TEXTURE_MIN_LOD:
5489 case GL_TEXTURE_MAX_LOD:
5490 case GL_TEXTURE_COMPARE_MODE:
5491 case GL_TEXTURE_COMPARE_FUNC:
5492 if (context->getClientMajorVersion() < 3)
5493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005494 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005495 return false;
5496 }
5497 break;
5498
5499 case GL_TEXTURE_SRGB_DECODE_EXT:
5500 if (!context->getExtensions().textureSRGBDecode)
5501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005502 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005503 return false;
5504 }
5505 break;
5506
Yunchao Hebacaa712018-01-30 14:01:39 +08005507 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5508 if (context->getClientVersion() < Version(3, 1))
5509 {
5510 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5511 return false;
5512 }
5513 break;
5514
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005515 case GL_GENERATE_MIPMAP:
5516 case GL_TEXTURE_CROP_RECT_OES:
5517 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5518 // after GL_OES_draw_texture functionality implemented
5519 if (context->getClientMajorVersion() > 1)
5520 {
5521 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5522 return false;
5523 }
5524 break;
Geoff Lang79b91402018-10-04 15:11:30 -04005525
5526 case GL_MEMORY_SIZE_ANGLE:
5527 if (!context->getExtensions().memorySize)
5528 {
5529 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
5530 return false;
5531 }
5532 break;
5533
Jamie Madillbe849e42017-05-02 15:49:00 -04005534 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005536 return false;
5537 }
5538
5539 if (length)
5540 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005541 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005542 }
5543 return true;
5544}
5545
5546bool ValidateGetVertexAttribBase(Context *context,
5547 GLuint index,
5548 GLenum pname,
5549 GLsizei *length,
5550 bool pointer,
5551 bool pureIntegerEntryPoint)
5552{
5553 if (length)
5554 {
5555 *length = 0;
5556 }
5557
5558 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005560 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005561 return false;
5562 }
5563
5564 if (index >= context->getCaps().maxVertexAttributes)
5565 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005566 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 return false;
5568 }
5569
5570 if (pointer)
5571 {
5572 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5573 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005574 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005575 return false;
5576 }
5577 }
5578 else
5579 {
5580 switch (pname)
5581 {
5582 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5583 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5584 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5585 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5586 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5587 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5588 case GL_CURRENT_VERTEX_ATTRIB:
5589 break;
5590
5591 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5592 static_assert(
5593 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5594 "ANGLE extension enums not equal to GL enums.");
5595 if (context->getClientMajorVersion() < 3 &&
5596 !context->getExtensions().instancedArrays)
5597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005598 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5599 "requires OpenGL ES 3.0 or "
5600 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005601 return false;
5602 }
5603 break;
5604
5605 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5606 if (context->getClientMajorVersion() < 3)
5607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005608 context->handleError(
5609 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005610 return false;
5611 }
5612 break;
5613
5614 case GL_VERTEX_ATTRIB_BINDING:
5615 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5616 if (context->getClientVersion() < ES_3_1)
5617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005618 context->handleError(InvalidEnum()
5619 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005620 return false;
5621 }
5622 break;
5623
5624 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005625 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005626 return false;
5627 }
5628 }
5629
5630 if (length)
5631 {
5632 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5633 {
5634 *length = 4;
5635 }
5636 else
5637 {
5638 *length = 1;
5639 }
5640 }
5641
5642 return true;
5643}
5644
Jamie Madill4928b7c2017-06-20 12:57:39 -04005645bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005646 GLint x,
5647 GLint y,
5648 GLsizei width,
5649 GLsizei height,
5650 GLenum format,
5651 GLenum type,
5652 GLsizei bufSize,
5653 GLsizei *length,
5654 GLsizei *columns,
5655 GLsizei *rows,
5656 void *pixels)
5657{
5658 if (length != nullptr)
5659 {
5660 *length = 0;
5661 }
5662 if (rows != nullptr)
5663 {
5664 *rows = 0;
5665 }
5666 if (columns != nullptr)
5667 {
5668 *columns = 0;
5669 }
5670
5671 if (width < 0 || height < 0)
5672 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005673 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005674 return false;
5675 }
5676
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005677 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005678
Jamie Madill427064d2018-04-13 16:20:34 -04005679 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005680 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005681 return false;
5682 }
5683
Jamie Madille98b1b52018-03-08 09:47:23 -05005684 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005685 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005686 return false;
5687 }
5688
Jamie Madill690c8eb2018-03-12 15:20:03 -04005689 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005690 ASSERT(framebuffer);
5691
5692 if (framebuffer->getReadBufferState() == GL_NONE)
5693 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005694 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005695 return false;
5696 }
5697
5698 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5699 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5700 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5701 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5702 // situation is an application error that would lead to a crash in ANGLE.
5703 if (readBuffer == nullptr)
5704 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005706 return false;
5707 }
5708
Martin Radev28031682017-07-28 14:47:56 +03005709 // ANGLE_multiview, Revision 1:
5710 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005711 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5712 // in the current read framebuffer is more than one.
5713 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005714 {
5715 context->handleError(InvalidFramebufferOperation()
5716 << "Attempting to read from a multi-view framebuffer.");
5717 return false;
5718 }
5719
Geoff Lang280ba992017-04-18 16:30:58 -04005720 if (context->getExtensions().webglCompatibility)
5721 {
5722 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5723 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5724 // and type before validating the combination of format and type. However, the
5725 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5726 // verifies that GL_INVALID_OPERATION is generated.
5727 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5728 // dEQP/WebGL.
5729 if (!ValidReadPixelsFormatEnum(context, format))
5730 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005731 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005732 return false;
5733 }
5734
5735 if (!ValidReadPixelsTypeEnum(context, type))
5736 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005737 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005738 return false;
5739 }
5740 }
5741
Jamie Madill690c8eb2018-03-12 15:20:03 -04005742 GLenum currentFormat = GL_NONE;
5743 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5744
5745 GLenum currentType = GL_NONE;
5746 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5747
Jamie Madillbe849e42017-05-02 15:49:00 -04005748 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5749
5750 bool validFormatTypeCombination =
5751 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5752
5753 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5754 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005755 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005756 return false;
5757 }
5758
5759 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005760 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005761 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5762 {
5763 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005764 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005765 return false;
5766 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005767 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5768 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5769 {
5770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5771 return false;
5772 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005773
5774 // .. the data would be packed to the buffer object such that the memory writes required
5775 // would exceed the data store size.
5776 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005777 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005778 const auto &pack = context->getGLState().getPackState();
5779
Jamie Madillca2ff382018-07-11 09:01:17 -04005780 GLuint endByte = 0;
5781 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005782 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005783 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 return false;
5785 }
5786
Jamie Madillbe849e42017-05-02 15:49:00 -04005787 if (bufSize >= 0)
5788 {
5789 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5790 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005791 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005792 return false;
5793 }
5794 }
5795
5796 if (pixelPackBuffer != nullptr)
5797 {
5798 CheckedNumeric<size_t> checkedEndByte(endByte);
5799 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5800 checkedEndByte += checkedOffset;
5801
5802 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5803 {
5804 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005805 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005806 return false;
5807 }
5808 }
5809
5810 if (pixelPackBuffer == nullptr && length != nullptr)
5811 {
5812 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5813 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005814 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 return false;
5816 }
5817
5818 *length = static_cast<GLsizei>(endByte);
5819 }
5820
Geoff Langa953b522018-02-21 16:56:23 -05005821 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005822 angle::CheckedNumeric<int> clippedExtent(length);
5823 if (start < 0)
5824 {
5825 // "subtract" the area that is less than 0
5826 clippedExtent += start;
5827 }
5828
Geoff Langa953b522018-02-21 16:56:23 -05005829 angle::CheckedNumeric<int> readExtent = start;
5830 readExtent += length;
5831 if (!readExtent.IsValid())
5832 {
5833 return false;
5834 }
5835
5836 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005837 {
5838 // Subtract the region to the right of the read buffer
5839 clippedExtent -= (readExtent - bufferSize);
5840 }
5841
5842 if (!clippedExtent.IsValid())
5843 {
Geoff Langa953b522018-02-21 16:56:23 -05005844 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005845 }
5846
Geoff Langa953b522018-02-21 16:56:23 -05005847 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5848 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005849 };
5850
Geoff Langa953b522018-02-21 16:56:23 -05005851 GLsizei writtenColumns = 0;
5852 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5853 {
5854 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5855 return false;
5856 }
5857
5858 GLsizei writtenRows = 0;
5859 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5860 {
5861 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5862 return false;
5863 }
5864
Jamie Madillbe849e42017-05-02 15:49:00 -04005865 if (columns != nullptr)
5866 {
Geoff Langa953b522018-02-21 16:56:23 -05005867 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005868 }
5869
5870 if (rows != nullptr)
5871 {
Geoff Langa953b522018-02-21 16:56:23 -05005872 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005873 }
5874
5875 return true;
5876}
5877
5878template <typename ParamType>
5879bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005880 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005881 GLenum pname,
5882 GLsizei bufSize,
5883 const ParamType *params)
5884{
5885 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5886 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005888 return false;
5889 }
5890
5891 if (context->getTargetTexture(target) == nullptr)
5892 {
5893 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005895 return false;
5896 }
5897
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005898 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005899 if (bufSize >= 0 && bufSize < minBufSize)
5900 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005902 return false;
5903 }
5904
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005905 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5906 {
5907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5908 return false;
5909 }
5910
Jamie Madillbe849e42017-05-02 15:49:00 -04005911 switch (pname)
5912 {
5913 case GL_TEXTURE_WRAP_R:
5914 case GL_TEXTURE_SWIZZLE_R:
5915 case GL_TEXTURE_SWIZZLE_G:
5916 case GL_TEXTURE_SWIZZLE_B:
5917 case GL_TEXTURE_SWIZZLE_A:
5918 case GL_TEXTURE_BASE_LEVEL:
5919 case GL_TEXTURE_MAX_LEVEL:
5920 case GL_TEXTURE_COMPARE_MODE:
5921 case GL_TEXTURE_COMPARE_FUNC:
5922 case GL_TEXTURE_MIN_LOD:
5923 case GL_TEXTURE_MAX_LOD:
5924 if (context->getClientMajorVersion() < 3)
5925 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005926 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005927 return false;
5928 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005929 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005931 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5932 "available without "
5933 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005934 return false;
5935 }
5936 break;
5937
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005938 case GL_GENERATE_MIPMAP:
5939 case GL_TEXTURE_CROP_RECT_OES:
5940 if (context->getClientMajorVersion() > 1)
5941 {
5942 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5943 return false;
5944 }
5945 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005946 default:
5947 break;
5948 }
5949
Olli Etuahod310a432018-08-24 15:40:23 +03005950 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005951 {
5952 switch (pname)
5953 {
5954 case GL_TEXTURE_MIN_FILTER:
5955 case GL_TEXTURE_MAG_FILTER:
5956 case GL_TEXTURE_WRAP_S:
5957 case GL_TEXTURE_WRAP_T:
5958 case GL_TEXTURE_WRAP_R:
5959 case GL_TEXTURE_MIN_LOD:
5960 case GL_TEXTURE_MAX_LOD:
5961 case GL_TEXTURE_COMPARE_MODE:
5962 case GL_TEXTURE_COMPARE_FUNC:
5963 context->handleError(InvalidEnum()
5964 << "Invalid parameter for 2D multisampled textures.");
5965 return false;
5966 }
5967 }
5968
Jamie Madillbe849e42017-05-02 15:49:00 -04005969 switch (pname)
5970 {
5971 case GL_TEXTURE_WRAP_S:
5972 case GL_TEXTURE_WRAP_T:
5973 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005974 {
5975 bool restrictedWrapModes =
5976 target == TextureType::External || target == TextureType::Rectangle;
5977 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005978 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005979 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005980 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005981 }
5982 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005983
5984 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005985 {
5986 bool restrictedMinFilter =
5987 target == TextureType::External || target == TextureType::Rectangle;
5988 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005989 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005990 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005991 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005992 }
5993 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005994
5995 case GL_TEXTURE_MAG_FILTER:
5996 if (!ValidateTextureMagFilterValue(context, params))
5997 {
5998 return false;
5999 }
6000 break;
6001
6002 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04006003 if (!context->getExtensions().textureUsage)
6004 {
6005 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6006 return false;
6007 }
6008
Jamie Madillbe849e42017-05-02 15:49:00 -04006009 switch (ConvertToGLenum(params[0]))
6010 {
6011 case GL_NONE:
6012 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
6013 break;
6014
6015 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006016 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006017 return false;
6018 }
6019 break;
6020
6021 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07006022 {
6023 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6024 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04006025 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006026 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006027 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006028 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6029 }
6030 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006031
6032 case GL_TEXTURE_MIN_LOD:
6033 case GL_TEXTURE_MAX_LOD:
6034 // any value is permissible
6035 break;
6036
6037 case GL_TEXTURE_COMPARE_MODE:
6038 if (!ValidateTextureCompareModeValue(context, params))
6039 {
6040 return false;
6041 }
6042 break;
6043
6044 case GL_TEXTURE_COMPARE_FUNC:
6045 if (!ValidateTextureCompareFuncValue(context, params))
6046 {
6047 return false;
6048 }
6049 break;
6050
6051 case GL_TEXTURE_SWIZZLE_R:
6052 case GL_TEXTURE_SWIZZLE_G:
6053 case GL_TEXTURE_SWIZZLE_B:
6054 case GL_TEXTURE_SWIZZLE_A:
6055 switch (ConvertToGLenum(params[0]))
6056 {
6057 case GL_RED:
6058 case GL_GREEN:
6059 case GL_BLUE:
6060 case GL_ALPHA:
6061 case GL_ZERO:
6062 case GL_ONE:
6063 break;
6064
6065 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006066 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006067 return false;
6068 }
6069 break;
6070
6071 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006072 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006074 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006075 return false;
6076 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006077 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006079 context->handleError(InvalidOperation()
6080 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006081 return false;
6082 }
Olli Etuahod310a432018-08-24 15:40:23 +03006083 if ((target == TextureType::_2DMultisample ||
6084 target == TextureType::_2DMultisampleArray) &&
6085 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006086 {
6087 context->handleError(InvalidOperation()
6088 << "Base level must be 0 for multisampled textures.");
6089 return false;
6090 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006091 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006092 {
6093 context->handleError(InvalidOperation()
6094 << "Base level must be 0 for rectangle textures.");
6095 return false;
6096 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006097 break;
6098
6099 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006100 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006102 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006103 return false;
6104 }
6105 break;
6106
6107 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6108 if (context->getClientVersion() < Version(3, 1))
6109 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006110 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006111 return false;
6112 }
6113 switch (ConvertToGLenum(params[0]))
6114 {
6115 case GL_DEPTH_COMPONENT:
6116 case GL_STENCIL_INDEX:
6117 break;
6118
6119 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006120 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006121 return false;
6122 }
6123 break;
6124
6125 case GL_TEXTURE_SRGB_DECODE_EXT:
6126 if (!ValidateTextureSRGBDecodeValue(context, params))
6127 {
6128 return false;
6129 }
6130 break;
6131
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006132 case GL_GENERATE_MIPMAP:
6133 case GL_TEXTURE_CROP_RECT_OES:
6134 if (context->getClientMajorVersion() > 1)
6135 {
6136 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6137 return false;
6138 }
6139 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006140 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006141 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006142 return false;
6143 }
6144
6145 return true;
6146}
6147
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006148template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6149template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006150
Jamie Madill5b772312018-03-08 20:28:32 -05006151bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006152{
6153 if (index >= MAX_VERTEX_ATTRIBS)
6154 {
6155 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6156 return false;
6157 }
6158
6159 return true;
6160}
6161
6162bool ValidateGetActiveUniformBlockivBase(Context *context,
6163 GLuint program,
6164 GLuint uniformBlockIndex,
6165 GLenum pname,
6166 GLsizei *length)
6167{
6168 if (length)
6169 {
6170 *length = 0;
6171 }
6172
6173 if (context->getClientMajorVersion() < 3)
6174 {
6175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6176 return false;
6177 }
6178
6179 Program *programObject = GetValidProgram(context, program);
6180 if (!programObject)
6181 {
6182 return false;
6183 }
6184
6185 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6186 {
6187 context->handleError(InvalidValue()
6188 << "uniformBlockIndex exceeds active uniform block count.");
6189 return false;
6190 }
6191
6192 switch (pname)
6193 {
6194 case GL_UNIFORM_BLOCK_BINDING:
6195 case GL_UNIFORM_BLOCK_DATA_SIZE:
6196 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6197 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6198 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6199 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6200 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6201 break;
6202
6203 default:
6204 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6205 return false;
6206 }
6207
6208 if (length)
6209 {
6210 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6211 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006212 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006213 programObject->getUniformBlockByIndex(uniformBlockIndex);
6214 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6215 }
6216 else
6217 {
6218 *length = 1;
6219 }
6220 }
6221
6222 return true;
6223}
6224
Jamie Madill9696d072017-08-26 23:19:57 -04006225template <typename ParamType>
6226bool ValidateSamplerParameterBase(Context *context,
6227 GLuint sampler,
6228 GLenum pname,
6229 GLsizei bufSize,
6230 ParamType *params)
6231{
6232 if (context->getClientMajorVersion() < 3)
6233 {
6234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6235 return false;
6236 }
6237
6238 if (!context->isSampler(sampler))
6239 {
6240 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6241 return false;
6242 }
6243
6244 const GLsizei minBufSize = 1;
6245 if (bufSize >= 0 && bufSize < minBufSize)
6246 {
6247 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6248 return false;
6249 }
6250
6251 switch (pname)
6252 {
6253 case GL_TEXTURE_WRAP_S:
6254 case GL_TEXTURE_WRAP_T:
6255 case GL_TEXTURE_WRAP_R:
6256 if (!ValidateTextureWrapModeValue(context, params, false))
6257 {
6258 return false;
6259 }
6260 break;
6261
6262 case GL_TEXTURE_MIN_FILTER:
6263 if (!ValidateTextureMinFilterValue(context, params, false))
6264 {
6265 return false;
6266 }
6267 break;
6268
6269 case GL_TEXTURE_MAG_FILTER:
6270 if (!ValidateTextureMagFilterValue(context, params))
6271 {
6272 return false;
6273 }
6274 break;
6275
6276 case GL_TEXTURE_MIN_LOD:
6277 case GL_TEXTURE_MAX_LOD:
6278 // any value is permissible
6279 break;
6280
6281 case GL_TEXTURE_COMPARE_MODE:
6282 if (!ValidateTextureCompareModeValue(context, params))
6283 {
6284 return false;
6285 }
6286 break;
6287
6288 case GL_TEXTURE_COMPARE_FUNC:
6289 if (!ValidateTextureCompareFuncValue(context, params))
6290 {
6291 return false;
6292 }
6293 break;
6294
6295 case GL_TEXTURE_SRGB_DECODE_EXT:
6296 if (!ValidateTextureSRGBDecodeValue(context, params))
6297 {
6298 return false;
6299 }
6300 break;
6301
Luc Ferron1b1a8642018-01-23 15:12:01 -05006302 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6303 {
6304 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6305 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6306 {
6307 return false;
6308 }
6309 }
6310 break;
6311
Jamie Madill9696d072017-08-26 23:19:57 -04006312 default:
6313 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6314 return false;
6315 }
6316
6317 return true;
6318}
6319
6320template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6321template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6322
6323bool ValidateGetSamplerParameterBase(Context *context,
6324 GLuint sampler,
6325 GLenum pname,
6326 GLsizei *length)
6327{
6328 if (length)
6329 {
6330 *length = 0;
6331 }
6332
6333 if (context->getClientMajorVersion() < 3)
6334 {
6335 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6336 return false;
6337 }
6338
6339 if (!context->isSampler(sampler))
6340 {
6341 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6342 return false;
6343 }
6344
6345 switch (pname)
6346 {
6347 case GL_TEXTURE_WRAP_S:
6348 case GL_TEXTURE_WRAP_T:
6349 case GL_TEXTURE_WRAP_R:
6350 case GL_TEXTURE_MIN_FILTER:
6351 case GL_TEXTURE_MAG_FILTER:
6352 case GL_TEXTURE_MIN_LOD:
6353 case GL_TEXTURE_MAX_LOD:
6354 case GL_TEXTURE_COMPARE_MODE:
6355 case GL_TEXTURE_COMPARE_FUNC:
6356 break;
6357
Luc Ferron1b1a8642018-01-23 15:12:01 -05006358 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6359 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6360 {
6361 return false;
6362 }
6363 break;
6364
Jamie Madill9696d072017-08-26 23:19:57 -04006365 case GL_TEXTURE_SRGB_DECODE_EXT:
6366 if (!context->getExtensions().textureSRGBDecode)
6367 {
6368 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6369 return false;
6370 }
6371 break;
6372
6373 default:
6374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6375 return false;
6376 }
6377
6378 if (length)
6379 {
6380 *length = 1;
6381 }
6382 return true;
6383}
6384
6385bool ValidateGetInternalFormativBase(Context *context,
6386 GLenum target,
6387 GLenum internalformat,
6388 GLenum pname,
6389 GLsizei bufSize,
6390 GLsizei *numParams)
6391{
6392 if (numParams)
6393 {
6394 *numParams = 0;
6395 }
6396
6397 if (context->getClientMajorVersion() < 3)
6398 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006399 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006400 return false;
6401 }
6402
6403 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006404 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006405 {
6406 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6407 return false;
6408 }
6409
6410 switch (target)
6411 {
6412 case GL_RENDERBUFFER:
6413 break;
6414
6415 case GL_TEXTURE_2D_MULTISAMPLE:
Yizhou Jiang7818a852018-09-06 15:02:04 +08006416 if (context->getClientVersion() < ES_3_1 &&
6417 !context->getExtensions().textureMultisample)
Jamie Madill9696d072017-08-26 23:19:57 -04006418 {
Yizhou Jiang7818a852018-09-06 15:02:04 +08006419 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
6420 MultisampleTextureExtensionOrES31Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006421 return false;
6422 }
6423 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006424 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6425 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006426 {
6427 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
6428 return false;
6429 }
6430 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006431 default:
6432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6433 return false;
6434 }
6435
6436 if (bufSize < 0)
6437 {
6438 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6439 return false;
6440 }
6441
6442 GLsizei maxWriteParams = 0;
6443 switch (pname)
6444 {
6445 case GL_NUM_SAMPLE_COUNTS:
6446 maxWriteParams = 1;
6447 break;
6448
6449 case GL_SAMPLES:
6450 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6451 break;
6452
6453 default:
6454 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6455 return false;
6456 }
6457
6458 if (numParams)
6459 {
6460 // glGetInternalFormativ will not overflow bufSize
6461 *numParams = std::min(bufSize, maxWriteParams);
6462 }
6463
6464 return true;
6465}
6466
Jamie Madille98b1b52018-03-08 09:47:23 -05006467bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6468{
Jamie Madill427064d2018-04-13 16:20:34 -04006469 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006470 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03006471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006472 return false;
6473 }
6474 return true;
6475}
6476
Lingfeng Yang038dd532018-03-29 17:31:52 -07006477bool ValidateMultitextureUnit(Context *context, GLenum texture)
6478{
6479 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6480 {
6481 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6482 return false;
6483 }
6484 return true;
6485}
6486
Olli Etuahod310a432018-08-24 15:40:23 +03006487bool ValidateTexStorageMultisample(Context *context,
6488 TextureType target,
6489 GLsizei samples,
6490 GLint internalFormat,
6491 GLsizei width,
6492 GLsizei height)
6493{
6494 const Caps &caps = context->getCaps();
6495 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6496 static_cast<GLuint>(height) > caps.max2DTextureSize)
6497 {
6498 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureWidthOrHeightOutOfRange);
6499 return false;
6500 }
6501
6502 if (samples == 0)
6503 {
6504 ANGLE_VALIDATION_ERR(context, InvalidValue(), SamplesZero);
6505 return false;
6506 }
6507
6508 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6509 if (!formatCaps.textureAttachment)
6510 {
6511 ANGLE_VALIDATION_ERR(context, InvalidEnum(), RenderableInternalFormat);
6512 return false;
6513 }
6514
6515 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6516 // is one of the unsized base internalformats listed in table 8.11.
6517 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6518 if (formatInfo.internalFormat == GL_NONE)
6519 {
6520 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnsizedInternalFormatUnsupported);
6521 return false;
6522 }
6523
6524 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6525 {
6526 ANGLE_VALIDATION_ERR(context, InvalidOperation(), SamplesOutOfRange);
6527 return false;
6528 }
6529
6530 Texture *texture = context->getTargetTexture(target);
6531 if (!texture || texture->id() == 0)
6532 {
6533 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ZeroBoundToTarget);
6534 return false;
6535 }
6536
6537 if (texture->getImmutableFormat())
6538 {
6539 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ImmutableTextureBound);
6540 return false;
6541 }
6542 return true;
6543}
6544
Yizhou Jiang7818a852018-09-06 15:02:04 +08006545bool ValidateTexStorage2DMultisampleBase(Context *context,
6546 TextureType target,
6547 GLsizei samples,
6548 GLint internalFormat,
6549 GLsizei width,
6550 GLsizei height)
6551{
6552 if (target != TextureType::_2DMultisample)
6553 {
6554 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6555 return false;
6556 }
6557
6558 if (width < 1 || height < 1)
6559 {
6560 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
6561 return false;
6562 }
6563
6564 return ValidateTexStorageMultisample(context, target, samples, internalFormat, width, height);
6565}
Jamie Madillc29968b2016-01-20 11:17:23 -05006566} // namespace gl