blob: deab303c9dc8c9617730ec3bb44fca8be6738010 [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:
He Yunchaoced53ae2016-11-29 15:00:51 +0800513 return (context->getClientVersion() >= Version(3, 1));
Olli Etuahod310a432018-08-24 15:40:23 +0300514 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300515 return context->getExtensions().textureStorageMultisample2DArray;
Geoff Lang3b573612016-10-31 14:08:10 -0400516
He Yunchaoced53ae2016-11-29 15:00:51 +0800517 default:
518 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500519 }
Jamie Madill35d15012013-10-07 10:46:37 -0400520}
521
Jamie Madill5b772312018-03-08 20:28:32 -0500522bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500523{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800524 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500525 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800526 case TextureType::_2D:
527 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500528 return true;
529
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800530 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400531 return context->getExtensions().textureRectangle;
532
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500533 default:
534 return false;
535 }
536}
537
Jamie Madill5b772312018-03-08 20:28:32 -0500538bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500539{
540 switch (target)
541 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800542 case TextureType::_3D:
543 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300544 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500545
546 default:
547 return false;
548 }
549}
550
Ian Ewellbda75592016-04-18 17:25:54 -0400551// Most texture GL calls are not compatible with external textures, so we have a separate validation
552// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500553bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400554{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800555 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400556 (context->getExtensions().eglImageExternal ||
557 context->getExtensions().eglStreamConsumerExternal);
558}
559
Shannon Woods4dfed832014-03-17 20:03:39 -0400560// This function differs from ValidTextureTarget in that the target must be
561// usable as the destination of a 2D operation-- so a cube face is valid, but
562// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400563// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500564bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400565{
566 switch (target)
567 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800568 case TextureTarget::_2D:
569 case TextureTarget::CubeMapNegativeX:
570 case TextureTarget::CubeMapNegativeY:
571 case TextureTarget::CubeMapNegativeZ:
572 case TextureTarget::CubeMapPositiveX:
573 case TextureTarget::CubeMapPositiveY:
574 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800575 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800576 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400577 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800578 default:
579 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500580 }
581}
582
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800583bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400584 PrimitiveMode transformFeedbackPrimitiveMode,
585 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800586{
587 ASSERT(context);
588
589 if (!context->getExtensions().geometryShader)
590 {
591 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
592 // that does not match the current transform feedback object's draw mode (if transform
593 // feedback is active), (3.0.2, section 2.14, pg 86)
594 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
595 }
596
597 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400598 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800599 {
Jamie Madill493f9572018-05-24 19:52:15 -0400600 case PrimitiveMode::Points:
601 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
602 case PrimitiveMode::Lines:
603 case PrimitiveMode::LineStrip:
604 case PrimitiveMode::LineLoop:
605 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
606 case PrimitiveMode::Triangles:
607 case PrimitiveMode::TriangleFan:
608 case PrimitiveMode::TriangleStrip:
609 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800610 default:
611 UNREACHABLE();
612 return false;
613 }
614}
615
Jamie Madill5b772312018-03-08 20:28:32 -0500616bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400617 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400618 GLsizei count,
619 GLenum type,
620 const GLvoid *indices,
621 GLsizei primcount)
622{
623 if (primcount < 0)
624 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700625 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400626 return false;
627 }
628
629 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
630 {
631 return false;
632 }
633
Jamie Madill9fdaa492018-02-16 10:52:11 -0500634 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400635}
636
637bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400638 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400639 GLint first,
640 GLsizei count,
641 GLsizei primcount)
642{
643 if (primcount < 0)
644 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700645 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400646 return false;
647 }
648
649 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
650 {
651 return false;
652 }
653
Jamie Madill9fdaa492018-02-16 10:52:11 -0500654 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400655}
656
Jamie Madill5b772312018-03-08 20:28:32 -0500657bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400658{
659 // Verify there is at least one active attribute with a divisor of zero
660 const State &state = context->getGLState();
661
Jamie Madill785e8a02018-10-04 17:42:00 -0400662 Program *program = state.getLinkedProgram(context);
Jamie Madillbe849e42017-05-02 15:49:00 -0400663
664 const auto &attribs = state.getVertexArray()->getVertexAttributes();
665 const auto &bindings = state.getVertexArray()->getVertexBindings();
666 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
667 {
668 const VertexAttribute &attrib = attribs[attributeIndex];
669 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300670 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400671 {
672 return true;
673 }
674 }
675
Brandon Jonesafa75152017-07-21 13:11:29 -0700676 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400677 return false;
678}
679
Jamie Madill5b772312018-03-08 20:28:32 -0500680bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500681{
682 switch (target)
683 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800684 case TextureType::_3D:
685 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800686 return true;
687 default:
688 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400689 }
690}
691
Jamie Madill5b772312018-03-08 20:28:32 -0500692bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800693{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800694 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800695 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800696 case TextureType::_2D:
697 case TextureType::_2DArray:
698 case TextureType::_2DMultisample:
699 case TextureType::CubeMap:
700 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800701 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800702 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400703 return context->getExtensions().textureRectangle;
Olli Etuahod310a432018-08-24 15:40:23 +0300704 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300705 return context->getExtensions().textureStorageMultisample2DArray;
He Yunchao11b038b2016-11-22 21:24:04 +0800706 default:
707 return false;
708 }
709}
710
Jamie Madill5b772312018-03-08 20:28:32 -0500711bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500712{
He Yunchaoced53ae2016-11-29 15:00:51 +0800713 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
714 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400715 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500716
717 switch (target)
718 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800719 case GL_FRAMEBUFFER:
720 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400721
He Yunchaoced53ae2016-11-29 15:00:51 +0800722 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800723 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400724 return (context->getExtensions().framebufferBlit ||
725 context->getClientMajorVersion() >= 3);
726
He Yunchaoced53ae2016-11-29 15:00:51 +0800727 default:
728 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500729 }
730}
731
Jamie Madill5b772312018-03-08 20:28:32 -0500732bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400733{
Jamie Madillc29968b2016-01-20 11:17:23 -0500734 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400735 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800736 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400737 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800738 case TextureType::_2D:
739 case TextureType::_2DArray:
740 case TextureType::_2DMultisample:
Olli Etuahod310a432018-08-24 15:40:23 +0300741 case TextureType::_2DMultisampleArray:
742 // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
743 // level-of-detail" for multisample textures should be. Could maybe make it zero.
Jamie Madillc29968b2016-01-20 11:17:23 -0500744 maxDimension = caps.max2DTextureSize;
745 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800746 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800747 maxDimension = caps.maxCubeMapTextureSize;
748 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800749 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400750 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800751 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800752 maxDimension = caps.max3DTextureSize;
753 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800754 default:
755 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400756 }
757
Jamie Madill43da7c42018-08-01 11:34:49 -0400758 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400759}
760
Jamie Madill5b772312018-03-08 20:28:32 -0500761bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800762 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700763 GLint level,
764 GLsizei width,
765 GLsizei height,
766 GLsizei depth,
767 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400768{
Brandon Jones6cad5662017-06-14 13:25:13 -0700769 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400770 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700771 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400772 return false;
773 }
Austin Kinross08528e12015-10-07 16:24:40 -0700774 // TexSubImage parameters can be NPOT without textureNPOT extension,
775 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500776 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500777 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500778 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400779 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400780 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700781 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400782 return false;
783 }
784
785 if (!ValidMipLevel(context, target, level))
786 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700787 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400788 return false;
789 }
790
791 return true;
792}
793
Geoff Lang966c9402017-04-18 12:38:27 -0400794bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
795{
796 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
797 (size % blockSize == 0);
798}
799
Jamie Madill5b772312018-03-08 20:28:32 -0500800bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500801 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400802 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500803 GLsizei width,
804 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400805{
Jamie Madill43da7c42018-08-01 11:34:49 -0400806 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400807 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400808 {
809 return false;
810 }
811
Geoff Lang966c9402017-04-18 12:38:27 -0400812 if (width < 0 || height < 0)
813 {
814 return false;
815 }
816
817 if (CompressedTextureFormatRequiresExactSize(internalFormat))
818 {
819 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
820 // block size for level 0 but WebGL disallows this.
821 bool smallerThanBlockSizeAllowed =
822 level > 0 || !context->getExtensions().webglCompatibility;
823
824 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
825 smallerThanBlockSizeAllowed) ||
826 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
827 smallerThanBlockSizeAllowed))
828 {
829 return false;
830 }
831 }
832
833 return true;
834}
835
Jamie Madill5b772312018-03-08 20:28:32 -0500836bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400837 GLenum internalFormat,
838 GLint xoffset,
839 GLint yoffset,
840 GLsizei width,
841 GLsizei height,
842 size_t textureWidth,
843 size_t textureHeight)
844{
Jamie Madill43da7c42018-08-01 11:34:49 -0400845 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400846 if (!formatInfo.compressed)
847 {
848 return false;
849 }
850
Geoff Lang44ff5a72017-02-03 15:15:43 -0500851 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400852 {
853 return false;
854 }
855
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500856 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400857 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500858 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400859 yoffset % formatInfo.compressedBlockHeight != 0)
860 {
861 return false;
862 }
863
864 // Allowed to either have data that is a multiple of block size or is smaller than the block
865 // size but fills the entire mip
866 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
867 static_cast<size_t>(width) == textureWidth &&
868 static_cast<size_t>(height) == textureHeight;
869 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
870 (height % formatInfo.compressedBlockHeight) == 0;
871 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400872 {
873 return false;
874 }
875 }
876
Geoff Langd4f180b2013-09-24 13:57:44 -0400877 return true;
878}
879
Jamie Madill5b772312018-03-08 20:28:32 -0500880bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800881 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400882 GLsizei width,
883 GLsizei height,
884 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400885 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400886 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400887 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400888 GLsizei imageSize)
889{
Jamie Madill43da7c42018-08-01 11:34:49 -0400890 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400891 if (pixelUnpackBuffer == nullptr && imageSize < 0)
892 {
893 // Checks are not required
894 return true;
895 }
896
897 // ...the data would be unpacked from the buffer object such that the memory reads required
898 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400899 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400900 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400901 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400902 const auto &unpack = context->getGLState().getUnpackState();
903
Jamie Madill7f232932018-09-12 11:03:06 -0400904 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
905 GLuint endByte = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400906 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400907 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400908 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400909 return false;
910 }
911
Geoff Langff5b2d52016-09-07 11:32:23 -0400912 if (pixelUnpackBuffer)
913 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400914 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400915 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
916 checkedEndByte += checkedOffset;
917
918 if (!checkedEndByte.IsValid() ||
919 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
920 {
921 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400922 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400923 return false;
924 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800925 if (context->getExtensions().webglCompatibility &&
926 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
927 {
928 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
929 PixelUnpackBufferBoundForTransformFeedback);
930 return false;
931 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400932 }
933 else
934 {
935 ASSERT(imageSize >= 0);
936 if (pixels == nullptr && imageSize != 0)
937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500938 context->handleError(InvalidOperation()
939 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400940 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400941 }
942
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400943 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500945 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400946 return false;
947 }
948 }
949
950 return true;
951}
952
Corentin Wallezad3ae902018-03-09 13:40:42 -0500953bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500954{
Geoff Lang37dde692014-01-31 16:34:54 -0500955 switch (queryType)
956 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500957 case QueryType::AnySamples:
958 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400959 return context->getClientMajorVersion() >= 3 ||
960 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500961 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800962 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500963 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800964 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500965 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800966 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500967 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800968 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800969 default:
970 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500971 }
972}
973
Jamie Madill5b772312018-03-08 20:28:32 -0500974bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400975 GLenum type,
976 GLboolean normalized,
977 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400978 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400979 bool pureInteger)
980{
981 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400982 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
983 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
984 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
985 // parameter exceeds 255.
986 constexpr GLsizei kMaxWebGLStride = 255;
987 if (stride > kMaxWebGLStride)
988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500989 context->handleError(InvalidValue()
990 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400991 return false;
992 }
993
994 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
995 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
996 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
997 // or an INVALID_OPERATION error is generated.
998 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
999 size_t typeSize = GetVertexFormatTypeSize(internalType);
1000
1001 ASSERT(isPow2(typeSize) && typeSize > 0);
1002 size_t sizeMask = (typeSize - 1);
1003 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1004 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001005 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001006 return false;
1007 }
1008
1009 if ((stride & sizeMask) != 0)
1010 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001011 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001012 return false;
1013 }
1014
1015 return true;
1016}
1017
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001018Program *GetValidProgramNoResolve(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001019{
He Yunchaoced53ae2016-11-29 15:00:51 +08001020 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1021 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1022 // or program object and INVALID_OPERATION if the provided name identifies an object
1023 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001024
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001025 Program *validProgram = context->getProgramNoResolveLink(id);
Dian Xiang769769a2015-09-09 15:20:08 -07001026
1027 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001028 {
Dian Xiang769769a2015-09-09 15:20:08 -07001029 if (context->getShader(id))
1030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001032 }
1033 else
1034 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001035 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001036 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001037 }
Dian Xiang769769a2015-09-09 15:20:08 -07001038
1039 return validProgram;
1040}
1041
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001042Program *GetValidProgram(Context *context, GLuint id)
1043{
1044 Program *program = GetValidProgramNoResolve(context, id);
1045 if (program)
1046 {
Jamie Madill785e8a02018-10-04 17:42:00 -04001047 program->resolveLink(context);
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001048 }
1049 return program;
1050}
1051
Jamie Madill5b772312018-03-08 20:28:32 -05001052Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001053{
1054 // See ValidProgram for spec details.
1055
1056 Shader *validShader = context->getShader(id);
1057
1058 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001059 {
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001060 if (context->getProgramNoResolveLink(id))
Dian Xiang769769a2015-09-09 15:20:08 -07001061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001063 }
1064 else
1065 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001066 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001067 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001068 }
Dian Xiang769769a2015-09-09 15:20:08 -07001069
1070 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001071}
1072
Jamie Madill43da7c42018-08-01 11:34:49 -04001073bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001074{
Geoff Langfa125c92017-10-24 13:01:46 -04001075 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001076 {
Geoff Langfa125c92017-10-24 13:01:46 -04001077 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1078 {
1079 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1080 return false;
1081 }
Jamie Madillb4472272014-07-03 10:38:55 -04001082
Geoff Langfa125c92017-10-24 13:01:46 -04001083 // Color attachment 0 is validated below because it is always valid
1084 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001085 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001086 {
Geoff Langfa125c92017-10-24 13:01:46 -04001087 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001088 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001089 }
1090 }
1091 else
1092 {
1093 switch (attachment)
1094 {
Geoff Langfa125c92017-10-24 13:01:46 -04001095 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001096 case GL_DEPTH_ATTACHMENT:
1097 case GL_STENCIL_ATTACHMENT:
1098 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001099
He Yunchaoced53ae2016-11-29 15:00:51 +08001100 case GL_DEPTH_STENCIL_ATTACHMENT:
1101 if (!context->getExtensions().webglCompatibility &&
1102 context->getClientMajorVersion() < 3)
1103 {
Geoff Langfa125c92017-10-24 13:01:46 -04001104 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001105 return false;
1106 }
1107 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001108
He Yunchaoced53ae2016-11-29 15:00:51 +08001109 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001110 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001112 }
1113 }
1114
1115 return true;
1116}
1117
Jamie Madill5b772312018-03-08 20:28:32 -05001118bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001119 GLenum target,
1120 GLsizei samples,
1121 GLenum internalformat,
1122 GLsizei width,
1123 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001124{
1125 switch (target)
1126 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001127 case GL_RENDERBUFFER:
1128 break;
1129 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001130 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001131 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001132 }
1133
1134 if (width < 0 || height < 0 || samples < 0)
1135 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001136 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001137 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001138 }
1139
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001140 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1141 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1142
1143 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001144 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001146 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001147 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001148 }
1149
1150 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1151 // 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 -08001152 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001153 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001154 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001155 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001156 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001158 }
1159
Geoff Langaae65a42014-05-26 12:43:44 -04001160 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001162 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001163 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001164 }
1165
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001166 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001167 if (handle == 0)
1168 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001170 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001171 }
1172
1173 return true;
1174}
1175
Jamie Madill43da7c42018-08-01 11:34:49 -04001176bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001177 GLenum target,
1178 GLenum attachment,
1179 GLenum renderbuffertarget,
1180 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001181{
Geoff Lange8afa902017-09-27 15:00:43 -04001182 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001184 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001185 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001186 }
1187
Jamie Madill43da7c42018-08-01 11:34:49 -04001188 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001189
Jamie Madill84115c92015-04-23 15:00:07 -04001190 ASSERT(framebuffer);
1191 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001194 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001195 }
1196
Jamie Madillb4472272014-07-03 10:38:55 -04001197 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001198 {
Jamie Madillb4472272014-07-03 10:38:55 -04001199 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001200 }
1201
Jamie Madillab9d82c2014-01-21 16:38:14 -05001202 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1203 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1204 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1205 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1206 if (renderbuffer != 0)
1207 {
1208 if (!context->getRenderbuffer(renderbuffer))
1209 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001210 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001211 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001212 }
1213 }
1214
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001215 return true;
1216}
1217
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001218bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001219 GLint srcX0,
1220 GLint srcY0,
1221 GLint srcX1,
1222 GLint srcY1,
1223 GLint dstX0,
1224 GLint dstY0,
1225 GLint dstX1,
1226 GLint dstY1,
1227 GLbitfield mask,
1228 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001229{
1230 switch (filter)
1231 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001232 case GL_NEAREST:
1233 break;
1234 case GL_LINEAR:
1235 break;
1236 default:
Olli Etuahof0e3c192018-08-15 13:37:21 +03001237 ANGLE_VALIDATION_ERR(context, InvalidEnum(), BlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001238 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001239 }
1240
1241 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1242 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001243 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001244 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001245 }
1246
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1248 // color buffer, leaving only nearest being unfiltered from above
1249 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1250 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001252 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001253 }
1254
Jamie Madill7f232932018-09-12 11:03:06 -04001255 const auto &glState = context->getGLState();
1256 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1257 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001258
1259 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001261 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001262 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001263 }
1264
Jamie Madill427064d2018-04-13 16:20:34 -04001265 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001266 {
Jamie Madill48faf802014-11-06 15:27:22 -05001267 return false;
1268 }
1269
Jamie Madill427064d2018-04-13 16:20:34 -04001270 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001271 {
Jamie Madill48faf802014-11-06 15:27:22 -05001272 return false;
1273 }
1274
Qin Jiajiaaef92162018-02-27 13:51:44 +08001275 if (readFramebuffer->id() == drawFramebuffer->id())
1276 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001277 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001278 return false;
1279 }
1280
Jamie Madille98b1b52018-03-08 09:47:23 -05001281 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001282 {
Geoff Langb1196682014-07-23 13:47:29 -04001283 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001284 }
1285
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001286 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1287 // always run it in order to avoid triggering driver bugs.
1288 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1289 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001290 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001291 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1292 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001293 }
1294
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1296
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297 if (mask & GL_COLOR_BUFFER_BIT)
1298 {
Jamie Madill7f232932018-09-12 11:03:06 -04001299 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1300 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301
He Yunchao66a41a22016-12-15 16:45:05 +08001302 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001303 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001304 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305
Geoff Langa15472a2015-08-11 11:48:03 -04001306 for (size_t drawbufferIdx = 0;
1307 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001308 {
Geoff Langa15472a2015-08-11 11:48:03 -04001309 const FramebufferAttachment *attachment =
1310 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1311 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001313 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314
Geoff Langb2f3d052013-08-13 12:49:27 -04001315 // The GL ES 3.0.2 spec (pg 193) states that:
1316 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001317 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1318 // as well
1319 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1320 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001321 // Changes with EXT_color_buffer_float:
1322 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001323 GLenum readComponentType = readFormat.info->componentType;
1324 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001325 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001326 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001327 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001328 drawComponentType == GL_SIGNED_NORMALIZED);
1329
1330 if (extensions.colorBufferFloat)
1331 {
1332 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1333 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1334
1335 if (readFixedOrFloat != drawFixedOrFloat)
1336 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001337 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1338 BlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001339 return false;
1340 }
1341 }
1342 else if (readFixedPoint != drawFixedPoint)
1343 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001344 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1345 BlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001346 return false;
1347 }
1348
1349 if (readComponentType == GL_UNSIGNED_INT &&
1350 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001352 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1353 BlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001354 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355 }
1356
Jamie Madill6163c752015-12-07 16:32:59 -05001357 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001359 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1360 BlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001361 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 }
1363
Jamie Madilla3944d42016-07-22 22:13:26 -04001364 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001365 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001367 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1368 BlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001369 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
Geoff Lange4915782017-04-12 15:19:07 -04001371
1372 if (context->getExtensions().webglCompatibility &&
1373 *readColorBuffer == *attachment)
1374 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001375 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001376 return false;
1377 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001378 }
1379 }
1380
Jamie Madilla3944d42016-07-22 22:13:26 -04001381 if ((readFormat.info->componentType == GL_INT ||
1382 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1383 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001385 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 }
He Yunchao66a41a22016-12-15 16:45:05 +08001389 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1390 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1391 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1392 // situation is an application error that would lead to a crash in ANGLE.
1393 else if (drawFramebuffer->hasEnabledDrawBuffer())
1394 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001395 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001396 return false;
1397 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 }
1399
He Yunchaoced53ae2016-11-29 15:00:51 +08001400 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001401 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1402 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001404 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001405 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001406 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001407 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001408 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001409 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001411 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412 {
Kenneth Russell69382852017-07-21 16:38:44 -04001413 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001415 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1416 BlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001417 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001419
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001420 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001421 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001422 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1423 BlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001424 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 }
Geoff Lange4915782017-04-12 15:19:07 -04001426
1427 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1428 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001429 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001430 return false;
1431 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 }
He Yunchao66a41a22016-12-15 16:45:05 +08001433 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1434 else if (drawBuffer)
1435 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001436 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001437 return false;
1438 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001439 }
1440 }
1441
Martin Radeva3ed4572017-07-27 18:29:37 +03001442 // ANGLE_multiview, Revision 1:
1443 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001444 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1445 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1446 // views in the current read framebuffer is more than one.
1447 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001448 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001449 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001450 return false;
1451 }
1452 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1453 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001454 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001455 return false;
1456 }
1457
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001458 return true;
1459}
1460
Jamie Madill4928b7c2017-06-20 12:57:39 -04001461bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001462 GLint x,
1463 GLint y,
1464 GLsizei width,
1465 GLsizei height,
1466 GLenum format,
1467 GLenum type,
1468 GLsizei bufSize,
1469 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001470 GLsizei *columns,
1471 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001472 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001473{
1474 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001475 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001476 return false;
1477 }
1478
Brandon Jonesd1049182018-03-28 10:02:20 -07001479 GLsizei writeLength = 0;
1480 GLsizei writeColumns = 0;
1481 GLsizei writeRows = 0;
1482
1483 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1484 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001485 {
Geoff Langb1196682014-07-23 13:47:29 -04001486 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001487 }
1488
Brandon Jonesd1049182018-03-28 10:02:20 -07001489 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001490 {
Geoff Langb1196682014-07-23 13:47:29 -04001491 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001492 }
1493
Brandon Jonesd1049182018-03-28 10:02:20 -07001494 SetRobustLengthParam(length, writeLength);
1495 SetRobustLengthParam(columns, writeColumns);
1496 SetRobustLengthParam(rows, writeRows);
1497
Jamie Madillc29968b2016-01-20 11:17:23 -05001498 return true;
1499}
1500
1501bool ValidateReadnPixelsEXT(Context *context,
1502 GLint x,
1503 GLint y,
1504 GLsizei width,
1505 GLsizei height,
1506 GLenum format,
1507 GLenum type,
1508 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001509 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001510{
1511 if (bufSize < 0)
1512 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001513 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001514 return false;
1515 }
1516
Geoff Lang62fce5b2016-09-30 10:46:35 -04001517 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001518 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001519}
Jamie Madill26e91952014-03-05 15:01:27 -05001520
Jamie Madill4928b7c2017-06-20 12:57:39 -04001521bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001522 GLint x,
1523 GLint y,
1524 GLsizei width,
1525 GLsizei height,
1526 GLenum format,
1527 GLenum type,
1528 GLsizei bufSize,
1529 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001530 GLsizei *columns,
1531 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001532 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001533{
Brandon Jonesd1049182018-03-28 10:02:20 -07001534 GLsizei writeLength = 0;
1535 GLsizei writeColumns = 0;
1536 GLsizei writeRows = 0;
1537
Geoff Lang62fce5b2016-09-30 10:46:35 -04001538 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001539 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001540 return false;
1541 }
1542
Brandon Jonesd1049182018-03-28 10:02:20 -07001543 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1544 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001545 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001546 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001547 }
1548
Brandon Jonesd1049182018-03-28 10:02:20 -07001549 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001550 {
1551 return false;
1552 }
1553
Brandon Jonesd1049182018-03-28 10:02:20 -07001554 SetRobustLengthParam(length, writeLength);
1555 SetRobustLengthParam(columns, writeColumns);
1556 SetRobustLengthParam(rows, writeRows);
1557
Geoff Lang62fce5b2016-09-30 10:46:35 -04001558 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001559}
1560
Jamie Madill43da7c42018-08-01 11:34:49 -04001561bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001562{
1563 if (!context->getExtensions().occlusionQueryBoolean &&
1564 !context->getExtensions().disjointTimerQuery)
1565 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001566 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001567 return false;
1568 }
1569
Olli Etuaho41997e72016-03-10 13:38:39 +02001570 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001571}
1572
Jamie Madill43da7c42018-08-01 11:34:49 -04001573bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001574{
1575 if (!context->getExtensions().occlusionQueryBoolean &&
1576 !context->getExtensions().disjointTimerQuery)
1577 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001578 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001579 return false;
1580 }
1581
Olli Etuaho41997e72016-03-10 13:38:39 +02001582 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001583}
1584
Jamie Madill43da7c42018-08-01 11:34:49 -04001585bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001586{
1587 if (!context->getExtensions().occlusionQueryBoolean &&
1588 !context->getExtensions().disjointTimerQuery)
1589 {
1590 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1591 return false;
1592 }
1593
1594 return true;
1595}
1596
Jamie Madill43da7c42018-08-01 11:34:49 -04001597bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001598{
1599 if (!ValidQueryType(context, target))
1600 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001601 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001602 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001603 }
1604
1605 if (id == 0)
1606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001607 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001608 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001609 }
1610
1611 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1612 // of zero, if the active query object name for <target> is non-zero (for the
1613 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1614 // the active query for either target is non-zero), if <id> is the name of an
1615 // existing query object whose type does not match <target>, or if <id> is the
1616 // active query object name for any query type, the error INVALID_OPERATION is
1617 // generated.
1618
1619 // Ensure no other queries are active
1620 // NOTE: If other queries than occlusion are supported, we will need to check
1621 // separately that:
1622 // a) The query ID passed is not the current active query for any target/type
1623 // b) There are no active queries for the requested target (and in the case
1624 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1625 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001626
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001627 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001629 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001630 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001631 }
1632
1633 Query *queryObject = context->getQuery(id, true, target);
1634
1635 // check that name was obtained with glGenQueries
1636 if (!queryObject)
1637 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001639 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001640 }
1641
1642 // check for type mismatch
1643 if (queryObject->getType() != target)
1644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001645 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001646 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001647 }
1648
1649 return true;
1650}
1651
Jamie Madill43da7c42018-08-01 11:34:49 -04001652bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001653{
1654 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001655 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001656 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001657 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001658 return false;
1659 }
1660
1661 return ValidateBeginQueryBase(context, target, id);
1662}
1663
Jamie Madill43da7c42018-08-01 11:34:49 -04001664bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001665{
1666 if (!ValidQueryType(context, target))
1667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001668 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001669 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001670 }
1671
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001672 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001673
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001674 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001676 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001677 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001678 }
1679
Jamie Madill45c785d2014-05-13 14:09:34 -04001680 return true;
1681}
1682
Jamie Madill43da7c42018-08-01 11:34:49 -04001683bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684{
1685 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001686 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001687 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001688 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001689 return false;
1690 }
1691
1692 return ValidateEndQueryBase(context, target);
1693}
1694
Corentin Wallezad3ae902018-03-09 13:40:42 -05001695bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001696{
1697 if (!context->getExtensions().disjointTimerQuery)
1698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001699 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700 return false;
1701 }
1702
Corentin Wallezad3ae902018-03-09 13:40:42 -05001703 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001704 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001705 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001706 return false;
1707 }
1708
1709 Query *queryObject = context->getQuery(id, true, target);
1710 if (queryObject == nullptr)
1711 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001712 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713 return false;
1714 }
1715
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001716 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001717 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001719 return false;
1720 }
1721
1722 return true;
1723}
1724
Corentin Wallezad3ae902018-03-09 13:40:42 -05001725bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001726{
Geoff Lang2186c382016-10-14 10:54:54 -04001727 if (numParams)
1728 {
1729 *numParams = 0;
1730 }
1731
Corentin Wallezad3ae902018-03-09 13:40:42 -05001732 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001733 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001734 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001735 return false;
1736 }
1737
1738 switch (pname)
1739 {
1740 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001741 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001743 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744 return false;
1745 }
1746 break;
1747 case GL_QUERY_COUNTER_BITS_EXT:
1748 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001749 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752 return false;
1753 }
1754 break;
1755 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001756 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001757 return false;
1758 }
1759
Geoff Lang2186c382016-10-14 10:54:54 -04001760 if (numParams)
1761 {
1762 // All queries return only one value
1763 *numParams = 1;
1764 }
1765
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001766 return true;
1767}
1768
Corentin Wallezad3ae902018-03-09 13:40:42 -05001769bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770{
1771 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001772 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001773 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001774 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001775 return false;
1776 }
1777
Geoff Lang2186c382016-10-14 10:54:54 -04001778 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001779}
1780
Geoff Lang2186c382016-10-14 10:54:54 -04001781bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001782 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001783 GLenum pname,
1784 GLsizei bufSize,
1785 GLsizei *length,
1786 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001787{
Geoff Lang2186c382016-10-14 10:54:54 -04001788 if (!ValidateRobustEntryPoint(context, bufSize))
1789 {
1790 return false;
1791 }
1792
Brandon Jonesd1049182018-03-28 10:02:20 -07001793 GLsizei numParams = 0;
1794
1795 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001796 {
1797 return false;
1798 }
1799
Brandon Jonesd1049182018-03-28 10:02:20 -07001800 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001801 {
1802 return false;
1803 }
1804
Brandon Jonesd1049182018-03-28 10:02:20 -07001805 SetRobustLengthParam(length, numParams);
1806
Geoff Lang2186c382016-10-14 10:54:54 -04001807 return true;
1808}
1809
1810bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1811{
1812 if (numParams)
1813 {
1814 *numParams = 0;
1815 }
1816
Corentin Wallezad3ae902018-03-09 13:40:42 -05001817 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001818
1819 if (!queryObject)
1820 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001821 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001822 return false;
1823 }
1824
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001825 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001826 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001827 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001828 return false;
1829 }
1830
1831 switch (pname)
1832 {
1833 case GL_QUERY_RESULT_EXT:
1834 case GL_QUERY_RESULT_AVAILABLE_EXT:
1835 break;
1836
1837 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001838 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001839 return false;
1840 }
1841
Geoff Lang2186c382016-10-14 10:54:54 -04001842 if (numParams)
1843 {
1844 *numParams = 1;
1845 }
1846
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001847 return true;
1848}
1849
1850bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1851{
1852 if (!context->getExtensions().disjointTimerQuery)
1853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001854 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001855 return false;
1856 }
Geoff Lang2186c382016-10-14 10:54:54 -04001857 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1858}
1859
1860bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1861 GLuint id,
1862 GLenum pname,
1863 GLsizei bufSize,
1864 GLsizei *length,
1865 GLint *params)
1866{
1867 if (!context->getExtensions().disjointTimerQuery)
1868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001869 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001870 return false;
1871 }
1872
1873 if (!ValidateRobustEntryPoint(context, bufSize))
1874 {
1875 return false;
1876 }
1877
Brandon Jonesd1049182018-03-28 10:02:20 -07001878 GLsizei numParams = 0;
1879
1880 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001881 {
1882 return false;
1883 }
1884
Brandon Jonesd1049182018-03-28 10:02:20 -07001885 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001886 {
1887 return false;
1888 }
1889
Brandon Jonesd1049182018-03-28 10:02:20 -07001890 SetRobustLengthParam(length, numParams);
1891
Geoff Lang2186c382016-10-14 10:54:54 -04001892 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001893}
1894
1895bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1896{
1897 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001898 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001899 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001900 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001901 return false;
1902 }
Geoff Lang2186c382016-10-14 10:54:54 -04001903 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1904}
1905
1906bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1907 GLuint id,
1908 GLenum pname,
1909 GLsizei bufSize,
1910 GLsizei *length,
1911 GLuint *params)
1912{
1913 if (!context->getExtensions().disjointTimerQuery &&
1914 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1915 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001916 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001917 return false;
1918 }
1919
1920 if (!ValidateRobustEntryPoint(context, bufSize))
1921 {
1922 return false;
1923 }
1924
Brandon Jonesd1049182018-03-28 10:02:20 -07001925 GLsizei numParams = 0;
1926
1927 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001928 {
1929 return false;
1930 }
1931
Brandon Jonesd1049182018-03-28 10:02:20 -07001932 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001933 {
1934 return false;
1935 }
1936
Brandon Jonesd1049182018-03-28 10:02:20 -07001937 SetRobustLengthParam(length, numParams);
1938
Geoff Lang2186c382016-10-14 10:54:54 -04001939 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001940}
1941
1942bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1943{
1944 if (!context->getExtensions().disjointTimerQuery)
1945 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001946 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001947 return false;
1948 }
Geoff Lang2186c382016-10-14 10:54:54 -04001949 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1950}
1951
1952bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1953 GLuint id,
1954 GLenum pname,
1955 GLsizei bufSize,
1956 GLsizei *length,
1957 GLint64 *params)
1958{
1959 if (!context->getExtensions().disjointTimerQuery)
1960 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001961 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001962 return false;
1963 }
1964
1965 if (!ValidateRobustEntryPoint(context, bufSize))
1966 {
1967 return false;
1968 }
1969
Brandon Jonesd1049182018-03-28 10:02:20 -07001970 GLsizei numParams = 0;
1971
1972 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001973 {
1974 return false;
1975 }
1976
Brandon Jonesd1049182018-03-28 10:02:20 -07001977 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001978 {
1979 return false;
1980 }
1981
Brandon Jonesd1049182018-03-28 10:02:20 -07001982 SetRobustLengthParam(length, numParams);
1983
Geoff Lang2186c382016-10-14 10:54:54 -04001984 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001985}
1986
1987bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1988{
1989 if (!context->getExtensions().disjointTimerQuery)
1990 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001991 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001992 return false;
1993 }
Geoff Lang2186c382016-10-14 10:54:54 -04001994 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1995}
1996
1997bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1998 GLuint id,
1999 GLenum pname,
2000 GLsizei bufSize,
2001 GLsizei *length,
2002 GLuint64 *params)
2003{
2004 if (!context->getExtensions().disjointTimerQuery)
2005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002007 return false;
2008 }
2009
2010 if (!ValidateRobustEntryPoint(context, bufSize))
2011 {
2012 return false;
2013 }
2014
Brandon Jonesd1049182018-03-28 10:02:20 -07002015 GLsizei numParams = 0;
2016
2017 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002018 {
2019 return false;
2020 }
2021
Brandon Jonesd1049182018-03-28 10:02:20 -07002022 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002023 {
2024 return false;
2025 }
2026
Brandon Jonesd1049182018-03-28 10:02:20 -07002027 SetRobustLengthParam(length, numParams);
2028
Geoff Lang2186c382016-10-14 10:54:54 -04002029 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002030}
2031
Jamie Madill5b772312018-03-08 20:28:32 -05002032bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002033 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002034 GLint location,
2035 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002036 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002037{
Jiajia Qin5451d532017-11-16 17:16:34 +08002038 // TODO(Jiajia): Add image uniform check in future.
2039 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002040 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002041 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002042 return false;
2043 }
2044
Jiajia Qin5451d532017-11-16 17:16:34 +08002045 if (!program)
2046 {
2047 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2048 return false;
2049 }
2050
2051 if (!program->isLinked())
2052 {
2053 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2054 return false;
2055 }
2056
2057 if (location == -1)
2058 {
2059 // Silently ignore the uniform command
2060 return false;
2061 }
2062
2063 const auto &uniformLocations = program->getUniformLocations();
2064 size_t castedLocation = static_cast<size_t>(location);
2065 if (castedLocation >= uniformLocations.size())
2066 {
2067 context->handleError(InvalidOperation() << "Invalid uniform location");
2068 return false;
2069 }
2070
2071 const auto &uniformLocation = uniformLocations[castedLocation];
2072 if (uniformLocation.ignored)
2073 {
2074 // Silently ignore the uniform command
2075 return false;
2076 }
2077
2078 if (!uniformLocation.used())
2079 {
2080 context->handleError(InvalidOperation());
2081 return false;
2082 }
2083
2084 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2085
2086 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002087 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002088 {
2089 context->handleError(InvalidOperation());
2090 return false;
2091 }
2092
2093 *uniformOut = &uniform;
2094 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002095}
2096
Jamie Madill5b772312018-03-08 20:28:32 -05002097bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002098 GLenum uniformType,
2099 GLsizei count,
2100 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002101{
Jiajia Qin5451d532017-11-16 17:16:34 +08002102 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2103 // It is compatible with INT or BOOL.
2104 // Do these cheap tests first, for a little extra speed.
2105 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002106 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002107 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002108 }
2109
Jiajia Qin5451d532017-11-16 17:16:34 +08002110 if (IsSamplerType(uniformType))
2111 {
2112 // Check that the values are in range.
2113 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2114 for (GLsizei i = 0; i < count; ++i)
2115 {
2116 if (value[i] < 0 || value[i] >= max)
2117 {
2118 context->handleError(InvalidValue() << "sampler uniform value out of range");
2119 return false;
2120 }
2121 }
2122 return true;
2123 }
2124
2125 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2126 return false;
2127}
2128
Jamie Madill5b772312018-03-08 20:28:32 -05002129bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002130{
2131 // Check that the value type is compatible with uniform type.
2132 if (valueType == uniformType)
2133 {
2134 return true;
2135 }
2136
2137 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2138 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002139}
2140
Jamie Madill5b772312018-03-08 20:28:32 -05002141bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002142{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002143 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002144 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002145 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2146 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002147}
2148
Jamie Madill5b772312018-03-08 20:28:32 -05002149bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002150{
2151 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002152 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmana98a6472017-02-02 21:38:32 -05002153 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2154 ValidateUniform1ivValue(context, uniform->type, count, value);
2155}
2156
Jamie Madill5b772312018-03-08 20:28:32 -05002157bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002158 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002159 GLint location,
2160 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002161 GLboolean transpose)
2162{
Geoff Lang92019432017-11-20 13:09:34 -05002163 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002164 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002165 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002166 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002167 }
2168
Jamie Madill62d31cb2015-09-11 13:25:51 -04002169 const LinkedUniform *uniform = nullptr;
Jamie Madill785e8a02018-10-04 17:42:00 -04002170 Program *programObject = context->getGLState().getLinkedProgram(context);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002171 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2172 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002173}
2174
Jamie Madill5b772312018-03-08 20:28:32 -05002175bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002176{
2177 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002179 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002180 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002181 }
2182
Jamie Madill0af26e12015-03-05 19:54:33 -05002183 const Caps &caps = context->getCaps();
2184
Jamie Madill893ab082014-05-16 16:56:10 -04002185 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2186 {
2187 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2188
Jamie Madill0af26e12015-03-05 19:54:33 -05002189 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002191 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002192 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002193 }
2194 }
2195
2196 switch (pname)
2197 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002198 case GL_TEXTURE_BINDING_2D:
2199 case GL_TEXTURE_BINDING_CUBE_MAP:
2200 case GL_TEXTURE_BINDING_3D:
2201 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002202 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002203 break;
Olli Etuahod310a432018-08-24 15:40:23 +03002204 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
Olli Etuaho064458a2018-08-30 14:02:02 +03002205 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03002206 {
2207 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
2208 return false;
2209 }
2210 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002211 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2212 if (!context->getExtensions().textureRectangle)
2213 {
2214 context->handleError(InvalidEnum()
2215 << "ANGLE_texture_rectangle extension not present");
2216 return false;
2217 }
2218 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002219 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2220 if (!context->getExtensions().eglStreamConsumerExternal &&
2221 !context->getExtensions().eglImageExternal)
2222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002223 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2224 "nor GL_OES_EGL_image_external "
2225 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002226 return false;
2227 }
2228 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002229
He Yunchaoced53ae2016-11-29 15:00:51 +08002230 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2231 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002232 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002233 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2234 ASSERT(readFramebuffer);
2235
Jamie Madill427064d2018-04-13 16:20:34 -04002236 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002237 {
Geoff Langb1196682014-07-23 13:47:29 -04002238 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002239 }
2240
Jamie Madille98b1b52018-03-08 09:47:23 -05002241 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002242 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002244 return false;
2245 }
2246
Jamie Madille98b1b52018-03-08 09:47:23 -05002247 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002248 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002250 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002251 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002252 }
2253 }
2254 break;
2255
He Yunchaoced53ae2016-11-29 15:00:51 +08002256 default:
2257 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002258 }
2259
2260 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002261 if (*numParams == 0)
2262 {
2263 return false;
2264 }
2265
2266 return true;
2267}
2268
Brandon Jonesd1049182018-03-28 10:02:20 -07002269bool ValidateGetBooleanvRobustANGLE(Context *context,
2270 GLenum pname,
2271 GLsizei bufSize,
2272 GLsizei *length,
2273 GLboolean *params)
2274{
2275 GLenum nativeType;
2276 unsigned int numParams = 0;
2277
2278 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2279 {
2280 return false;
2281 }
2282
2283 SetRobustLengthParam(length, numParams);
2284
2285 return true;
2286}
2287
2288bool ValidateGetFloatvRobustANGLE(Context *context,
2289 GLenum pname,
2290 GLsizei bufSize,
2291 GLsizei *length,
2292 GLfloat *params)
2293{
2294 GLenum nativeType;
2295 unsigned int numParams = 0;
2296
2297 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2298 {
2299 return false;
2300 }
2301
2302 SetRobustLengthParam(length, numParams);
2303
2304 return true;
2305}
2306
2307bool ValidateGetIntegervRobustANGLE(Context *context,
2308 GLenum pname,
2309 GLsizei bufSize,
2310 GLsizei *length,
2311 GLint *data)
2312{
2313 GLenum nativeType;
2314 unsigned int numParams = 0;
2315
2316 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2317 {
2318 return false;
2319 }
2320
2321 SetRobustLengthParam(length, numParams);
2322
2323 return true;
2324}
2325
2326bool ValidateGetInteger64vRobustANGLE(Context *context,
2327 GLenum pname,
2328 GLsizei bufSize,
2329 GLsizei *length,
2330 GLint64 *data)
2331{
2332 GLenum nativeType;
2333 unsigned int numParams = 0;
2334
2335 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2336 {
2337 return false;
2338 }
2339
2340 if (nativeType == GL_INT_64_ANGLEX)
2341 {
2342 CastStateValues(context, nativeType, pname, numParams, data);
2343 return false;
2344 }
2345
2346 SetRobustLengthParam(length, numParams);
2347 return true;
2348}
2349
Jamie Madill5b772312018-03-08 20:28:32 -05002350bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002351 GLenum pname,
2352 GLsizei bufSize,
2353 GLenum *nativeType,
2354 unsigned int *numParams)
2355{
2356 if (!ValidateRobustEntryPoint(context, bufSize))
2357 {
2358 return false;
2359 }
2360
2361 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2362 {
2363 return false;
2364 }
2365
2366 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002367 {
2368 return false;
2369 }
2370
2371 return true;
2372}
2373
Jamie Madill5b772312018-03-08 20:28:32 -05002374bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002375 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002376 GLint level,
2377 GLenum internalformat,
2378 bool isSubImage,
2379 GLint xoffset,
2380 GLint yoffset,
2381 GLint zoffset,
2382 GLint x,
2383 GLint y,
2384 GLsizei width,
2385 GLsizei height,
2386 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002387 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002388{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002389 TextureType texType = TextureTargetToType(target);
2390
Brandon Jones6cad5662017-06-14 13:25:13 -07002391 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002392 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002393 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2394 return false;
2395 }
2396
2397 if (width < 0 || height < 0)
2398 {
2399 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002400 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002401 }
2402
He Yunchaoced53ae2016-11-29 15:00:51 +08002403 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2404 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002406 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002407 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002408 }
2409
2410 if (border != 0)
2411 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002412 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002413 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002414 }
2415
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002416 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002417 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002418 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002419 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002420 }
2421
Jamie Madill43da7c42018-08-01 11:34:49 -04002422 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002423 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002424 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002425 {
Geoff Langb1196682014-07-23 13:47:29 -04002426 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002427 }
2428
Jamie Madille98b1b52018-03-08 09:47:23 -05002429 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002430 {
Geoff Langb1196682014-07-23 13:47:29 -04002431 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002432 }
2433
Martin Radev138064f2016-07-15 12:03:41 +03002434 if (readFramebuffer->getReadBufferState() == GL_NONE)
2435 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002436 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002437 return false;
2438 }
2439
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002440 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2441 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002442 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002443 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002444 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2445 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002446 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002447 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002448 return false;
2449 }
2450
Martin Radev04e2c3b2017-07-27 16:54:35 +03002451 // ANGLE_multiview spec, Revision 1:
2452 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2453 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002454 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2455 // framebuffer is more than one.
2456 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002457 {
2458 context->handleError(InvalidFramebufferOperation()
2459 << "The active read framebuffer object has multiview attachments.");
2460 return false;
2461 }
2462
Jamie Madill43da7c42018-08-01 11:34:49 -04002463 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002464
Geoff Langaae65a42014-05-26 12:43:44 -04002465 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002466 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002467 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002468 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002469 maxDimension = caps.max2DTextureSize;
2470 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002471
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002472 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002473 maxDimension = caps.maxCubeMapTextureSize;
2474 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002475
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002476 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002477 maxDimension = caps.maxRectangleTextureSize;
2478 break;
2479
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002480 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002481 maxDimension = caps.max2DTextureSize;
2482 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002483
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002484 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002485 maxDimension = caps.max3DTextureSize;
2486 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002487
He Yunchaoced53ae2016-11-29 15:00:51 +08002488 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002489 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002490 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002491 }
2492
Jamie Madill43da7c42018-08-01 11:34:49 -04002493 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002494 if (!texture)
2495 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002496 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002497 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002498 }
2499
Geoff Lang69cce582015-09-17 13:20:36 -04002500 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002502 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002503 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002504 }
2505
Jamie Madill43da7c42018-08-01 11:34:49 -04002506 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002507 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002508 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002509
Geoff Lang966c9402017-04-18 12:38:27 -04002510 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002512 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002513 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002514 }
2515
2516 if (isSubImage)
2517 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002518 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2519 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2520 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002522 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002524 }
2525 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002526 else
2527 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002528 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002529 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002530 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002531 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002532 }
2533
Geoff Langeb66a6e2016-10-31 13:06:12 -04002534 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002536 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002537 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002538 }
2539
2540 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002541 if (static_cast<int>(width) > maxLevelDimension ||
2542 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002543 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002544 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002545 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002546 }
2547 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002548
Jamie Madill0c8abca2016-07-22 20:21:26 -04002549 if (textureFormatOut)
2550 {
2551 *textureFormatOut = texture->getFormat(target, level);
2552 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002553
2554 // Detect texture copying feedback loops for WebGL.
2555 if (context->getExtensions().webglCompatibility)
2556 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002557 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002558 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002559 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002560 return false;
2561 }
2562 }
2563
Jamie Madill560a8d82014-05-21 13:06:20 -04002564 return true;
2565}
2566
Jamie Madillb42162f2018-08-20 12:58:37 -04002567// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2568// completeness check.
2569const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002570{
2571 const Extensions &extensions = context->getExtensions();
Jamie Madill7f232932018-09-12 11:03:06 -04002572 const State &state = context->getGLState();
Jamie Madille7d80f32018-08-08 15:49:23 -04002573
2574 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2575 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2576 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madilld84b6732018-09-06 15:54:35 -04002577 VertexArray *vertexArray = state.getVertexArray();
2578 ASSERT(vertexArray);
2579
2580 if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
Jamie Madille7d80f32018-08-08 15:49:23 -04002581 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002582 return kErrorBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002583 }
2584
2585 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2586 // Section 6.10 of the WebGL 1.0 spec.
2587 Framebuffer *framebuffer = state.getDrawFramebuffer();
Jamie Madilld84b6732018-09-06 15:54:35 -04002588 ASSERT(framebuffer);
2589
Jamie Madille7d80f32018-08-08 15:49:23 -04002590 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2591 {
2592 ASSERT(framebuffer);
2593 const FramebufferAttachment *dsAttachment =
2594 framebuffer->getStencilOrDepthStencilAttachment();
2595 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2596 ASSERT(stencilBits <= 8);
2597
2598 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2599 if (depthStencilState.stencilTest && stencilBits > 0)
2600 {
2601 GLuint maxStencilValue = (1 << stencilBits) - 1;
2602
2603 bool differentRefs =
2604 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2605 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2606 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2607 (depthStencilState.stencilBackWritemask & maxStencilValue);
2608 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2609 (depthStencilState.stencilBackMask & maxStencilValue);
2610
2611 if (differentRefs || differentWritemasks || differentMasks)
2612 {
2613 if (!extensions.webglCompatibility)
2614 {
2615 WARN() << "This ANGLE implementation does not support separate front/back "
2616 "stencil writemasks, reference values, or stencil mask values.";
2617 }
Jamie Madillb42162f2018-08-20 12:58:37 -04002618 return kErrorStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002619 }
2620 }
2621 }
2622
2623 if (!framebuffer->isComplete(context))
2624 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002625 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2626 return kErrorDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002627 }
2628
2629 if (context->getStateCache().hasAnyEnabledClientAttrib())
2630 {
2631 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2632 {
2633 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2634 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2635 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2636 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madillb42162f2018-08-20 12:58:37 -04002637 return kErrorVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002638 }
2639
2640 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2641 {
2642 // This is an application error that would normally result in a crash, but we catch it
2643 // and return an error
Jamie Madillb42162f2018-08-20 12:58:37 -04002644 return kErrorVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002645 }
2646 }
2647
2648 // If we are running GLES1, there is no current program.
2649 if (context->getClientVersion() >= Version(2, 0))
2650 {
Jamie Madill785e8a02018-10-04 17:42:00 -04002651 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002652 if (!program)
2653 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002654 return kErrorProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002655 }
2656
2657 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2658 // vertex shader stage or fragment shader stage is a undefined behaviour.
2659 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2660 // produce undefined result.
2661 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2662 !program->hasLinkedShaderStage(ShaderType::Fragment))
2663 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002664 return kErrorNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002665 }
2666
2667 if (!program->validateSamplers(nullptr, context->getCaps()))
2668 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002669 return kErrorTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002670 }
2671
2672 if (extensions.multiview)
2673 {
2674 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2675 const int framebufferNumViews = framebuffer->getNumViews();
2676 if (framebufferNumViews != programNumViews)
2677 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002678 return kErrorMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002679 }
2680
2681 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2682 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2683 framebufferNumViews > 1)
2684 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002685 return kErrorMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002686 }
2687
2688 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2689 state.isQueryActive(QueryType::TimeElapsed))
2690 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002691 return kErrorMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002692 }
2693 }
2694
2695 // Uniform buffer validation
2696 for (unsigned int uniformBlockIndex = 0;
2697 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2698 {
2699 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Jamie Madill7f232932018-09-12 11:03:06 -04002700 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Jamie Madille7d80f32018-08-08 15:49:23 -04002701 const OffsetBindingPointer<Buffer> &uniformBuffer =
2702 state.getIndexedUniformBuffer(blockBinding);
2703
2704 if (uniformBuffer.get() == nullptr)
2705 {
2706 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002707 return kErrorUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002708 }
2709
2710 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2711 if (uniformBufferSize < uniformBlock.dataSize)
2712 {
2713 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002714 return kErrorUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002715 }
2716
2717 if (extensions.webglCompatibility &&
2718 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2719 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002720 return kErrorUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002721 }
2722 }
2723
2724 // Do some additonal WebGL-specific validation
2725 if (extensions.webglCompatibility)
2726 {
2727 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2728 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2729 transformFeedbackObject->buffersBoundForOtherUse())
2730 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002731 return kErrorTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002732 }
2733
2734 // Detect rendering feedback loops for WebGL.
2735 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2736 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002737 return kErrorFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002738 }
2739
2740 // Detect that the vertex shader input types match the attribute types
2741 if (!ValidateVertexShaderAttributeTypeMatch(context))
2742 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002743 return kErrorVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002744 }
2745
2746 // Detect that the color buffer types match the fragment shader output types
2747 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2748 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002749 return kErrorDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002750 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002751
2752 const VertexArray *vao = context->getGLState().getVertexArray();
2753 if (vao->hasTransformFeedbackBindingConflict(context))
2754 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002755 return kErrorVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002756 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002757 }
2758 }
2759
Jamie Madillb42162f2018-08-20 12:58:37 -04002760 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002761}
2762
Jamie Madill16e28fd2018-09-12 11:03:05 -04002763bool ValidateDrawMode(Context *context, PrimitiveMode mode)
Jamie Madill250d33f2014-06-06 17:09:03 -04002764{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002765 const Extensions &extensions = context->getExtensions();
2766
Jamie Madill1aeb1312014-06-20 13:21:25 -04002767 switch (mode)
2768 {
Jamie Madill493f9572018-05-24 19:52:15 -04002769 case PrimitiveMode::Points:
2770 case PrimitiveMode::Lines:
2771 case PrimitiveMode::LineLoop:
2772 case PrimitiveMode::LineStrip:
2773 case PrimitiveMode::Triangles:
2774 case PrimitiveMode::TriangleStrip:
2775 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002776 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002777
Jamie Madill493f9572018-05-24 19:52:15 -04002778 case PrimitiveMode::LinesAdjacency:
2779 case PrimitiveMode::LineStripAdjacency:
2780 case PrimitiveMode::TrianglesAdjacency:
2781 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002782 if (!extensions.geometryShader)
2783 {
2784 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2785 return false;
2786 }
2787 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002788 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002789 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002790 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002791 }
2792
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002793 // If we are running GLES1, there is no current program.
2794 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002795 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002796 const State &state = context->getGLState();
2797
Jamie Madill785e8a02018-10-04 17:42:00 -04002798 Program *program = state.getLinkedProgram(context);
Jamie Madille7d80f32018-08-08 15:49:23 -04002799 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002800
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002801 // Do geometry shader specific validations
2802 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002803 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002804 if (!IsCompatibleDrawModeWithGeometryShader(
2805 mode, program->getGeometryShaderInputPrimitiveType()))
2806 {
2807 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2808 IncompatibleDrawModeAgainstGeometryShader);
2809 return false;
2810 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002811 }
2812 }
2813
Jamie Madill9fdaa492018-02-16 10:52:11 -05002814 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002815}
2816
Jamie Madill16e28fd2018-09-12 11:03:05 -04002817bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
2818{
2819 if (!context->getStateCache().isValidDrawMode(mode))
2820 {
2821 return ValidateDrawMode(context, mode);
2822 }
2823
2824 if (count < 0)
2825 {
2826 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2827 return false;
2828 }
2829
2830 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2831 if (drawStatesError)
2832 {
2833 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2834
2835 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2836 // Incomplete.
2837 GLenum errorCode =
2838 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2839 : GL_INVALID_OPERATION);
2840 context->handleError(Error(errorCode, errorMessage));
2841 return false;
2842 }
2843
2844 return true;
2845}
2846
Jamie Madill5b772312018-03-08 20:28:32 -05002847bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002848 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002849 GLint first,
2850 GLsizei count,
2851 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002852{
Jamie Madillfd716582014-06-06 17:09:04 -04002853 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002854 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002855 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002856 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002857 }
2858
Jamie Madill16e28fd2018-09-12 11:03:05 -04002859 if (count < 0)
2860 {
2861 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2862 return false;
2863 }
2864
Jamie Madill7f232932018-09-12 11:03:06 -04002865 const State &state = context->getGLState();
2866 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002867 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002868 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002869 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002870 if (!ValidateTransformFeedbackPrimitiveMode(context,
2871 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002872 {
James Darpinian30b604d2018-03-12 17:26:57 -07002873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2874 return false;
2875 }
2876
2877 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2878 {
2879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2880 return false;
2881 }
Jamie Madillfd716582014-06-06 17:09:04 -04002882 }
2883
Jamie Madill16e28fd2018-09-12 11:03:05 -04002884 if (!context->getStateCache().isValidDrawMode(mode))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002885 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002886 return ValidateDrawMode(context, mode);
2887 }
2888
2889 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2890 if (drawStatesError)
2891 {
2892 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2893
2894 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2895 // Incomplete.
2896 GLenum errorCode =
2897 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2898 : GL_INVALID_OPERATION);
2899 context->handleError(Error(errorCode, errorMessage));
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002900 return false;
2901 }
2902
Corentin Wallez71168a02016-12-19 15:11:18 -08002903 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002904 // - first < 0 has been checked as an error condition.
2905 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002906 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002907 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002908 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002909 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002910 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2911 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2912 {
2913 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2914 return false;
2915 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002916
Jamie Madill2da53562018-08-01 11:34:47 -04002917 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002918 {
2919 return false;
2920 }
Jamie Madillfd716582014-06-06 17:09:04 -04002921 }
2922
2923 return true;
2924}
2925
He Yunchaoced53ae2016-11-29 15:00:51 +08002926bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002927 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002928 GLint first,
2929 GLsizei count,
2930 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002931{
Geoff Lang63c5a592017-09-27 14:08:16 -04002932 if (!context->getExtensions().instancedArrays)
2933 {
2934 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2935 return false;
2936 }
2937
Corentin Wallez170efbf2017-05-02 13:45:01 -04002938 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002939 {
2940 return false;
2941 }
2942
Corentin Wallez0dc97812017-06-22 14:38:44 -04002943 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002944}
2945
Jamie Madill493f9572018-05-24 19:52:15 -04002946bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002947{
Jamie Madill250d33f2014-06-06 17:09:03 -04002948 switch (type)
2949 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002950 case GL_UNSIGNED_BYTE:
2951 case GL_UNSIGNED_SHORT:
2952 break;
2953 case GL_UNSIGNED_INT:
2954 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2955 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002956 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002957 return false;
2958 }
2959 break;
2960 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002961 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002962 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002963 }
2964
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002965 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002966
Jamie Madill43da7c42018-08-01 11:34:49 -04002967 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002968 if (curTransformFeedback && curTransformFeedback->isActive() &&
2969 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002970 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002971 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2972 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2973 if (context->getExtensions().geometryShader)
2974 {
2975 if (!ValidateTransformFeedbackPrimitiveMode(
2976 context, curTransformFeedback->getPrimitiveMode(), mode))
2977 {
2978 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2979 return false;
2980 }
2981 }
2982 else
2983 {
2984 // It is an invalid operation to call DrawElements, DrawRangeElements or
2985 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2986 // 86)
2987 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2988 UnsupportedDrawModeForTransformFeedback);
2989 return false;
2990 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002991 }
2992
Jiajia Qind9671222016-11-29 16:30:31 +08002993 return true;
2994}
2995
Jamie Madill5b772312018-03-08 20:28:32 -05002996bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002997 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002998 GLsizei count,
2999 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003000 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003001 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003002{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003003 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003004 return false;
3005
3006 const State &state = context->getGLState();
3007
Corentin Wallez170efbf2017-05-02 13:45:01 -04003008 if (!ValidateDrawBase(context, mode, count))
3009 {
3010 return false;
3011 }
3012
Jamie Madill43da7c42018-08-01 11:34:49 -04003013 const VertexArray *vao = state.getVertexArray();
3014 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003015
Jamie Madill43da7c42018-08-01 11:34:49 -04003016 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003017
3018 if (context->getExtensions().webglCompatibility)
3019 {
3020 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3021 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3022 {
3023 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3024 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3025 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003026 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003027 return false;
3028 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003029
3030 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3031 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3032 // error is generated.
3033 if (reinterpret_cast<intptr_t>(indices) < 0)
3034 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003035 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003036 return false;
3037 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003038 }
Jamie Madillcc73f242018-08-01 11:34:48 -04003039 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
3040 {
3041 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3042 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3043 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3044 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3045 return false;
3046 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003047
3048 if (context->getExtensions().webglCompatibility ||
3049 !context->getGLState().areClientArraysEnabled())
3050 {
Brandon Jones2a018152018-06-08 15:59:26 -07003051 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003052 {
3053 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003054 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3055 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003056 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003057 return false;
3058 }
3059 }
3060
Jamie Madill9fdaa492018-02-16 10:52:11 -05003061 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003062 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003063 // This is an application error that would normally result in a crash, but we catch it and
3064 // return an error
3065 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3066 return false;
3067 }
3068
3069 if (count > 0 && elementArrayBuffer)
3070 {
3071 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3072 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3073 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3074 constexpr uint64_t kMaxTypeSize = 8;
3075 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3076 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3077 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3078
3079 uint64_t typeSize = typeBytes;
3080 uint64_t elementCount = static_cast<uint64_t>(count);
3081 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3082
3083 // Doing the multiplication here is overflow-safe
3084 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3085
3086 // The offset can be any value, check for overflows
3087 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3088 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003089 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003090 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3091 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003092 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003093
3094 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3095 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003096 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3098 return false;
3099 }
3100
3101 ASSERT(isPow2(typeSize) && typeSize > 0);
3102 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3103 {
3104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003105 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003106 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003107
3108 if (context->getExtensions().webglCompatibility &&
3109 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3110 {
3111 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3112 ElementArrayBufferBoundForTransformFeedback);
3113 return false;
3114 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003115 }
3116
Jamie Madill2da53562018-08-01 11:34:47 -04003117 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003118 {
3119 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003120 const DrawCallParams &params = context->getParams<DrawCallParams>();
3121 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3122 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003123
3124 // If we use an index greater than our maximum supported index range, return an error.
3125 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3126 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003127 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003128 {
3129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3130 return false;
3131 }
3132
Jamie Madill2da53562018-08-01 11:34:47 -04003133 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003134 {
3135 return false;
3136 }
3137
3138 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003139 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003140 }
3141
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003142 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003143}
3144
Jamie Madill5b772312018-03-08 20:28:32 -05003145bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003146 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003147 GLsizei count,
3148 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003149 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003150 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003151{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003152 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003153}
3154
Geoff Lang3edfe032015-09-04 16:38:24 -04003155bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003156 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003157 GLsizei count,
3158 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003159 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003160 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003161{
Geoff Lang63c5a592017-09-27 14:08:16 -04003162 if (!context->getExtensions().instancedArrays)
3163 {
3164 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3165 return false;
3166 }
3167
Corentin Wallez170efbf2017-05-02 13:45:01 -04003168 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003169 {
3170 return false;
3171 }
3172
Corentin Wallez0dc97812017-06-22 14:38:44 -04003173 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003174}
3175
He Yunchaoced53ae2016-11-29 15:00:51 +08003176bool ValidateFramebufferTextureBase(Context *context,
3177 GLenum target,
3178 GLenum attachment,
3179 GLuint texture,
3180 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003181{
Geoff Lange8afa902017-09-27 15:00:43 -04003182 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003183 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003184 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003185 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003186 }
3187
3188 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003189 {
3190 return false;
3191 }
3192
Jamie Madill55ec3b12014-07-03 10:38:57 -04003193 if (texture != 0)
3194 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003195 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003196
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003197 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003199 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003200 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003201 }
3202
3203 if (level < 0)
3204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003205 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003206 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003207 }
3208 }
3209
Jamie Madill43da7c42018-08-01 11:34:49 -04003210 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003211 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003212
Jamie Madill84115c92015-04-23 15:00:07 -04003213 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003216 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003217 }
3218
3219 return true;
3220}
3221
Geoff Langb1196682014-07-23 13:47:29 -04003222bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003223{
3224 if (program == 0)
3225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003226 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003227 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003228 }
3229
Jamie Madill43da7c42018-08-01 11:34:49 -04003230 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003231 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003232 {
3233 return false;
3234 }
3235
Jamie Madill0063c512014-08-25 15:47:53 -04003236 if (!programObject || !programObject->isLinked())
3237 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003239 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003240 }
3241
Geoff Lang7dd2e102014-11-10 15:19:26 -05003242 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003244 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003245 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003246 }
3247
Jamie Madill0063c512014-08-25 15:47:53 -04003248 return true;
3249}
3250
Geoff Langf41d0ee2016-10-07 13:04:23 -04003251static bool ValidateSizedGetUniform(Context *context,
3252 GLuint program,
3253 GLint location,
3254 GLsizei bufSize,
3255 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003256{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003257 if (length)
3258 {
3259 *length = 0;
3260 }
3261
Jamie Madill78f41802014-08-25 15:47:55 -04003262 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003263 {
Jamie Madill78f41802014-08-25 15:47:55 -04003264 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003265 }
3266
Geoff Langf41d0ee2016-10-07 13:04:23 -04003267 if (bufSize < 0)
3268 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003269 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003270 return false;
3271 }
3272
Jamie Madill44a6fbf2018-10-02 13:38:56 -04003273 Program *programObject = context->getProgramResolveLink(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003274 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003275
Jamie Madill78f41802014-08-25 15:47:55 -04003276 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003277 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003278 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003279 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003280 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003281 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003282 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003283 }
3284
Geoff Langf41d0ee2016-10-07 13:04:23 -04003285 if (length)
3286 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003287 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003288 }
3289
Jamie Madill0063c512014-08-25 15:47:53 -04003290 return true;
3291}
3292
He Yunchaoced53ae2016-11-29 15:00:51 +08003293bool ValidateGetnUniformfvEXT(Context *context,
3294 GLuint program,
3295 GLint location,
3296 GLsizei bufSize,
3297 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003298{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003299 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003300}
3301
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003302bool ValidateGetnUniformfvRobustANGLE(Context *context,
3303 GLuint program,
3304 GLint location,
3305 GLsizei bufSize,
3306 GLsizei *length,
3307 GLfloat *params)
3308{
3309 UNIMPLEMENTED();
3310 return false;
3311}
3312
He Yunchaoced53ae2016-11-29 15:00:51 +08003313bool ValidateGetnUniformivEXT(Context *context,
3314 GLuint program,
3315 GLint location,
3316 GLsizei bufSize,
3317 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003318{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003319 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3320}
3321
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003322bool ValidateGetnUniformivRobustANGLE(Context *context,
3323 GLuint program,
3324 GLint location,
3325 GLsizei bufSize,
3326 GLsizei *length,
3327 GLint *params)
3328{
3329 UNIMPLEMENTED();
3330 return false;
3331}
3332
3333bool ValidateGetnUniformuivRobustANGLE(Context *context,
3334 GLuint program,
3335 GLint location,
3336 GLsizei bufSize,
3337 GLsizei *length,
3338 GLuint *params)
3339{
3340 UNIMPLEMENTED();
3341 return false;
3342}
3343
Geoff Langf41d0ee2016-10-07 13:04:23 -04003344bool ValidateGetUniformfvRobustANGLE(Context *context,
3345 GLuint program,
3346 GLint location,
3347 GLsizei bufSize,
3348 GLsizei *length,
3349 GLfloat *params)
3350{
3351 if (!ValidateRobustEntryPoint(context, bufSize))
3352 {
3353 return false;
3354 }
3355
Brandon Jonesd1049182018-03-28 10:02:20 -07003356 GLsizei writeLength = 0;
3357
Geoff Langf41d0ee2016-10-07 13:04:23 -04003358 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003359 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3360 {
3361 return false;
3362 }
3363
3364 SetRobustLengthParam(length, writeLength);
3365
3366 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003367}
3368
3369bool ValidateGetUniformivRobustANGLE(Context *context,
3370 GLuint program,
3371 GLint location,
3372 GLsizei bufSize,
3373 GLsizei *length,
3374 GLint *params)
3375{
3376 if (!ValidateRobustEntryPoint(context, bufSize))
3377 {
3378 return false;
3379 }
3380
Brandon Jonesd1049182018-03-28 10:02:20 -07003381 GLsizei writeLength = 0;
3382
Geoff Langf41d0ee2016-10-07 13:04:23 -04003383 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003384 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3385 {
3386 return false;
3387 }
3388
3389 SetRobustLengthParam(length, writeLength);
3390
3391 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003392}
3393
3394bool ValidateGetUniformuivRobustANGLE(Context *context,
3395 GLuint program,
3396 GLint location,
3397 GLsizei bufSize,
3398 GLsizei *length,
3399 GLuint *params)
3400{
3401 if (!ValidateRobustEntryPoint(context, bufSize))
3402 {
3403 return false;
3404 }
3405
3406 if (context->getClientMajorVersion() < 3)
3407 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003409 return false;
3410 }
3411
Brandon Jonesd1049182018-03-28 10:02:20 -07003412 GLsizei writeLength = 0;
3413
Geoff Langf41d0ee2016-10-07 13:04:23 -04003414 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003415 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3416 {
3417 return false;
3418 }
3419
3420 SetRobustLengthParam(length, writeLength);
3421
3422 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003423}
3424
He Yunchaoced53ae2016-11-29 15:00:51 +08003425bool ValidateDiscardFramebufferBase(Context *context,
3426 GLenum target,
3427 GLsizei numAttachments,
3428 const GLenum *attachments,
3429 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003430{
3431 if (numAttachments < 0)
3432 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003433 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003434 return false;
3435 }
3436
3437 for (GLsizei i = 0; i < numAttachments; ++i)
3438 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003439 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003440 {
3441 if (defaultFramebuffer)
3442 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003443 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003444 return false;
3445 }
3446
3447 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003449 context->handleError(InvalidOperation() << "Requested color attachment is "
3450 "greater than the maximum supported "
3451 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003452 return false;
3453 }
3454 }
3455 else
3456 {
3457 switch (attachments[i])
3458 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003459 case GL_DEPTH_ATTACHMENT:
3460 case GL_STENCIL_ATTACHMENT:
3461 case GL_DEPTH_STENCIL_ATTACHMENT:
3462 if (defaultFramebuffer)
3463 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003464 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3465 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003466 return false;
3467 }
3468 break;
3469 case GL_COLOR:
3470 case GL_DEPTH:
3471 case GL_STENCIL:
3472 if (!defaultFramebuffer)
3473 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003474 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3475 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003476 return false;
3477 }
3478 break;
3479 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003480 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003481 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003482 }
3483 }
3484 }
3485
3486 return true;
3487}
3488
Austin Kinross6ee1e782015-05-29 17:05:37 -07003489bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3490{
Jamie Madill007530e2017-12-28 14:27:04 -05003491 if (!context->getExtensions().debugMarker)
3492 {
3493 // The debug marker calls should not set error state
3494 // However, it seems reasonable to set an error state if the extension is not enabled
3495 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3496 return false;
3497 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003498
Jamie Madill007530e2017-12-28 14:27:04 -05003499 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003500 if (length < 0)
3501 {
3502 return false;
3503 }
3504
3505 if (marker == nullptr)
3506 {
3507 return false;
3508 }
3509
3510 return true;
3511}
3512
3513bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3514{
Jamie Madill007530e2017-12-28 14:27:04 -05003515 if (!context->getExtensions().debugMarker)
3516 {
3517 // The debug marker calls should not set error state
3518 // However, it seems reasonable to set an error state if the extension is not enabled
3519 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3520 return false;
3521 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003522
Jamie Madill007530e2017-12-28 14:27:04 -05003523 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003524 if (length < 0)
3525 {
3526 return false;
3527 }
3528
3529 if (length > 0 && marker == nullptr)
3530 {
3531 return false;
3532 }
3533
3534 return true;
3535}
3536
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003537bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003538{
Geoff Langa8406172015-07-21 16:53:39 -04003539 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003541 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003542 return false;
3543 }
3544
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003545 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003546 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003547 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003548 if (!context->getExtensions().eglImage)
3549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003550 context->handleError(InvalidEnum()
3551 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003552 }
3553 break;
3554
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003555 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003556 if (!context->getExtensions().eglImageExternal)
3557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003558 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3559 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003560 }
Geoff Langa8406172015-07-21 16:53:39 -04003561 break;
3562
3563 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003564 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003565 return false;
3566 }
3567
Rafael Cintron05a449a2018-06-20 18:08:04 -07003568 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003569
Jamie Madill61e16b42017-06-19 11:13:23 -04003570 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003571 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003573 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003574 return false;
3575 }
3576
Jamie Madill007530e2017-12-28 14:27:04 -05003577 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003579 context->handleError(InvalidOperation()
3580 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003581 return false;
3582 }
3583
Yuly Novikov2eb54072018-08-22 16:41:26 -04003584 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003586 context->handleError(InvalidOperation()
3587 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003588 return false;
3589 }
3590
Geoff Langdcab33b2015-07-21 13:03:16 -04003591 return true;
3592}
3593
3594bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003595 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003596 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003597{
Geoff Langa8406172015-07-21 16:53:39 -04003598 if (!context->getExtensions().eglImage)
3599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003600 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003601 return false;
3602 }
3603
3604 switch (target)
3605 {
3606 case GL_RENDERBUFFER:
3607 break;
3608
3609 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003610 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003611 return false;
3612 }
3613
Rafael Cintron05a449a2018-06-20 18:08:04 -07003614 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003615
Jamie Madill61e16b42017-06-19 11:13:23 -04003616 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003617 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003619 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003620 return false;
3621 }
3622
Yuly Novikov2eb54072018-08-22 16:41:26 -04003623 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003625 context->handleError(InvalidOperation()
3626 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003627 return false;
3628 }
3629
Geoff Langdcab33b2015-07-21 13:03:16 -04003630 return true;
3631}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003632
3633bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3634{
Geoff Lang36167ab2015-12-07 10:27:14 -05003635 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003636 {
3637 // The default VAO should always exist
3638 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003639 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003640 return false;
3641 }
3642
3643 return true;
3644}
3645
Geoff Langc5629752015-12-07 16:29:04 -05003646bool ValidateProgramBinaryBase(Context *context,
3647 GLuint program,
3648 GLenum binaryFormat,
3649 const void *binary,
3650 GLint length)
3651{
3652 Program *programObject = GetValidProgram(context, program);
3653 if (programObject == nullptr)
3654 {
3655 return false;
3656 }
3657
3658 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3659 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3660 programBinaryFormats.end())
3661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003662 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003663 return false;
3664 }
3665
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003666 if (context->hasActiveTransformFeedback(program))
3667 {
3668 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003669 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3670 "is associated with an active transform "
3671 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003672 return false;
3673 }
3674
Geoff Langc5629752015-12-07 16:29:04 -05003675 return true;
3676}
3677
3678bool ValidateGetProgramBinaryBase(Context *context,
3679 GLuint program,
3680 GLsizei bufSize,
3681 GLsizei *length,
3682 GLenum *binaryFormat,
3683 void *binary)
3684{
3685 Program *programObject = GetValidProgram(context, program);
3686 if (programObject == nullptr)
3687 {
3688 return false;
3689 }
3690
3691 if (!programObject->isLinked())
3692 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003693 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003694 return false;
3695 }
3696
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003697 if (context->getCaps().programBinaryFormats.empty())
3698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003699 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003700 return false;
3701 }
3702
Geoff Langc5629752015-12-07 16:29:04 -05003703 return true;
3704}
Jamie Madillc29968b2016-01-20 11:17:23 -05003705
Jamie Madill5b772312018-03-08 20:28:32 -05003706bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003707{
3708 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003709 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003710 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003711 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3712 return false;
3713 }
3714 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3715 {
3716 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003717 return false;
3718 }
3719
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003720 ASSERT(context->getGLState().getDrawFramebuffer());
3721 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003722 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3723
3724 // This should come first before the check for the default frame buffer
3725 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3726 // rather than INVALID_OPERATION
3727 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3728 {
3729 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3730
3731 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003732 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3733 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003734 {
3735 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003736 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3737 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3738 // 3.1 is still a bit ambiguous about the error, but future specs are
3739 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003740 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003741 return false;
3742 }
3743 else if (bufs[colorAttachment] >= maxColorAttachment)
3744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003745 context->handleError(InvalidOperation()
3746 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003747 return false;
3748 }
3749 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3750 frameBufferId != 0)
3751 {
3752 // INVALID_OPERATION-GL is bound to buffer and ith argument
3753 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 context->handleError(InvalidOperation()
3755 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003756 return false;
3757 }
3758 }
3759
3760 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3761 // and n is not 1 or bufs is bound to value other than BACK and NONE
3762 if (frameBufferId == 0)
3763 {
3764 if (n != 1)
3765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003766 context->handleError(InvalidOperation()
3767 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003768 return false;
3769 }
3770
3771 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3772 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003773 context->handleError(
3774 InvalidOperation()
3775 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003776 return false;
3777 }
3778 }
3779
3780 return true;
3781}
3782
Geoff Lang496c02d2016-10-20 11:38:11 -07003783bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003784 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003785 GLenum pname,
3786 GLsizei *length,
3787 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003788{
Geoff Lang496c02d2016-10-20 11:38:11 -07003789 if (length)
3790 {
3791 *length = 0;
3792 }
3793
3794 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3795 {
3796 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003797 InvalidOperation()
3798 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003799 return false;
3800 }
3801
Corentin Walleze4477002017-12-01 14:39:58 -05003802 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003803 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003804 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003805 return false;
3806 }
3807
Geoff Lang496c02d2016-10-20 11:38:11 -07003808 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003809 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003810 case GL_BUFFER_MAP_POINTER:
3811 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003812
Geoff Lang496c02d2016-10-20 11:38:11 -07003813 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003814 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003815 return false;
3816 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003817
3818 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3819 // target bound to zero generate an INVALID_OPERATION error."
3820 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003821 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003823 context->handleError(InvalidOperation()
3824 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003825 return false;
3826 }
3827
Geoff Lang496c02d2016-10-20 11:38:11 -07003828 if (length)
3829 {
3830 *length = 1;
3831 }
3832
Olli Etuaho4f667482016-03-30 15:56:35 +03003833 return true;
3834}
3835
Corentin Wallez336129f2017-10-17 15:55:40 -04003836bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003837{
Corentin Walleze4477002017-12-01 14:39:58 -05003838 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003839 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003840 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003841 return false;
3842 }
3843
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003844 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003845
3846 if (buffer == nullptr || !buffer->isMapped())
3847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003848 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003849 return false;
3850 }
3851
3852 return true;
3853}
3854
3855bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003856 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003857 GLintptr offset,
3858 GLsizeiptr length,
3859 GLbitfield access)
3860{
Corentin Walleze4477002017-12-01 14:39:58 -05003861 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003863 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003864 return false;
3865 }
3866
Brandon Jones6cad5662017-06-14 13:25:13 -07003867 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003868 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003869 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3870 return false;
3871 }
3872
3873 if (length < 0)
3874 {
3875 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003876 return false;
3877 }
3878
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003879 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003880
3881 if (!buffer)
3882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003883 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003884 return false;
3885 }
3886
3887 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003888 CheckedNumeric<size_t> checkedOffset(offset);
3889 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003890
Jamie Madille2e406c2016-06-02 13:04:10 -04003891 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003893 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003894 return false;
3895 }
3896
3897 // Check for invalid bits in the mask
3898 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3899 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3900 GL_MAP_UNSYNCHRONIZED_BIT;
3901
3902 if (access & ~(allAccessBits))
3903 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003904 context->handleError(InvalidValue()
3905 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003906 return false;
3907 }
3908
3909 if (length == 0)
3910 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003911 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003912 return false;
3913 }
3914
3915 if (buffer->isMapped())
3916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003917 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003918 return false;
3919 }
3920
3921 // Check for invalid bit combinations
3922 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003924 context->handleError(InvalidOperation()
3925 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003926 return false;
3927 }
3928
3929 GLbitfield writeOnlyBits =
3930 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3931
3932 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003934 context->handleError(InvalidOperation()
3935 << "Invalid access bits when mapping buffer for reading: 0x"
3936 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003937 return false;
3938 }
3939
3940 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003942 context->handleError(
3943 InvalidOperation()
3944 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003945 return false;
3946 }
Geoff Lang79f71042017-08-14 16:43:43 -04003947
3948 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003949}
3950
3951bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003952 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003953 GLintptr offset,
3954 GLsizeiptr length)
3955{
Brandon Jones6cad5662017-06-14 13:25:13 -07003956 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003957 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003958 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3959 return false;
3960 }
3961
3962 if (length < 0)
3963 {
3964 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003965 return false;
3966 }
3967
Corentin Walleze4477002017-12-01 14:39:58 -05003968 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003970 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003971 return false;
3972 }
3973
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003974 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003975
3976 if (buffer == nullptr)
3977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003978 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003979 return false;
3980 }
3981
3982 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003984 context->handleError(InvalidOperation()
3985 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003986 return false;
3987 }
3988
3989 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003990 CheckedNumeric<size_t> checkedOffset(offset);
3991 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003992
Jamie Madille2e406c2016-06-02 13:04:10 -04003993 if (!checkedSize.IsValid() ||
3994 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003996 context->handleError(InvalidValue()
3997 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003998 return false;
3999 }
4000
4001 return true;
4002}
4003
Olli Etuaho41997e72016-03-10 13:38:39 +02004004bool ValidateGenOrDelete(Context *context, GLint n)
4005{
4006 if (n < 0)
4007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004008 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004009 return false;
4010 }
4011 return true;
4012}
4013
Jamie Madill5b772312018-03-08 20:28:32 -05004014bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004015{
4016 if (!context->getExtensions().robustClientMemory)
4017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004018 context->handleError(InvalidOperation()
4019 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004020 return false;
4021 }
4022
4023 if (bufSize < 0)
4024 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004025 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004026 return false;
4027 }
4028
4029 return true;
4030}
4031
Jamie Madill5b772312018-03-08 20:28:32 -05004032bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004033{
4034 if (bufSize < numParams)
4035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004036 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4037 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004038 return false;
4039 }
4040
4041 return true;
4042}
4043
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004044bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004045 GLenum target,
4046 GLenum attachment,
4047 GLenum pname,
4048 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004049{
Geoff Lange8afa902017-09-27 15:00:43 -04004050 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004051 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004052 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004053 return false;
4054 }
4055
4056 int clientVersion = context->getClientMajorVersion();
4057
4058 switch (pname)
4059 {
4060 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4061 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4062 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4063 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4064 break;
4065
Martin Radeve5285d22017-07-14 16:23:53 +03004066 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4067 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4068 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4069 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4070 if (clientVersion < 3 || !context->getExtensions().multiview)
4071 {
4072 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4073 return false;
4074 }
4075 break;
4076
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4078 if (clientVersion < 3 && !context->getExtensions().sRGB)
4079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004080 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004081 return false;
4082 }
4083 break;
4084
4085 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4086 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4087 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4088 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4089 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4090 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4091 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4092 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4093 if (clientVersion < 3)
4094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004095 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004096 return false;
4097 }
4098 break;
4099
Jiawei Shaoa8802472018-05-28 11:17:47 +08004100 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4101 if (!context->getExtensions().geometryShader)
4102 {
4103 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4104 return false;
4105 }
4106 break;
4107
Geoff Langff5b2d52016-09-07 11:32:23 -04004108 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004109 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004110 return false;
4111 }
4112
4113 // Determine if the attachment is a valid enum
4114 switch (attachment)
4115 {
4116 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004117 case GL_DEPTH:
4118 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004119 if (clientVersion < 3)
4120 {
Geoff Langfa125c92017-10-24 13:01:46 -04004121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004122 return false;
4123 }
4124 break;
4125
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004126 case GL_DEPTH_STENCIL_ATTACHMENT:
4127 if (clientVersion < 3 && !context->isWebGL1())
4128 {
4129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4130 return false;
4131 }
4132 break;
4133
Geoff Langfa125c92017-10-24 13:01:46 -04004134 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004135 case GL_DEPTH_ATTACHMENT:
4136 case GL_STENCIL_ATTACHMENT:
4137 break;
4138
4139 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004140 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4141 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004142 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4143 {
Geoff Langfa125c92017-10-24 13:01:46 -04004144 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004145 return false;
4146 }
4147 break;
4148 }
4149
4150 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4151 ASSERT(framebuffer);
4152
4153 if (framebuffer->id() == 0)
4154 {
4155 if (clientVersion < 3)
4156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004157 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004158 return false;
4159 }
4160
4161 switch (attachment)
4162 {
4163 case GL_BACK:
4164 case GL_DEPTH:
4165 case GL_STENCIL:
4166 break;
4167
4168 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004170 return false;
4171 }
4172 }
4173 else
4174 {
4175 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4176 {
4177 // Valid attachment query
4178 }
4179 else
4180 {
4181 switch (attachment)
4182 {
4183 case GL_DEPTH_ATTACHMENT:
4184 case GL_STENCIL_ATTACHMENT:
4185 break;
4186
4187 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004188 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004190 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004191 return false;
4192 }
4193 break;
4194
4195 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004196 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004197 return false;
4198 }
4199 }
4200 }
4201
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004202 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004203 if (attachmentObject)
4204 {
4205 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4206 attachmentObject->type() == GL_TEXTURE ||
4207 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4208
4209 switch (pname)
4210 {
4211 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4212 if (attachmentObject->type() != GL_RENDERBUFFER &&
4213 attachmentObject->type() != GL_TEXTURE)
4214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004215 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004216 return false;
4217 }
4218 break;
4219
4220 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4221 if (attachmentObject->type() != GL_TEXTURE)
4222 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004223 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004224 return false;
4225 }
4226 break;
4227
4228 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4229 if (attachmentObject->type() != GL_TEXTURE)
4230 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004231 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004232 return false;
4233 }
4234 break;
4235
4236 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4237 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4238 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004240 return false;
4241 }
4242 break;
4243
4244 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4245 if (attachmentObject->type() != GL_TEXTURE)
4246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004247 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004248 return false;
4249 }
4250 break;
4251
4252 default:
4253 break;
4254 }
4255 }
4256 else
4257 {
4258 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4259 // is NONE, then querying any other pname will generate INVALID_ENUM.
4260
4261 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4262 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4263 // INVALID_OPERATION for all other pnames
4264
4265 switch (pname)
4266 {
4267 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4268 break;
4269
4270 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4271 if (clientVersion < 3)
4272 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004273 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004274 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004275 return false;
4276 }
4277 break;
4278
4279 default:
4280 if (clientVersion < 3)
4281 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004282 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004283 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004284 return false;
4285 }
4286 else
4287 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004288 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004289 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004290 return false;
4291 }
4292 }
4293 }
4294
Martin Radeve5285d22017-07-14 16:23:53 +03004295 if (numParams)
4296 {
4297 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4298 {
4299 // Only when the viewport offsets are queried we can have a varying number of output
4300 // parameters.
4301 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4302 *numParams = numViews * 2;
4303 }
4304 else
4305 {
4306 // For all other queries we can have only one output parameter.
4307 *numParams = 1;
4308 }
4309 }
4310
Geoff Langff5b2d52016-09-07 11:32:23 -04004311 return true;
4312}
4313
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004314bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004315 GLenum target,
4316 GLenum attachment,
4317 GLenum pname,
4318 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004319 GLsizei *length,
4320 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004321{
4322 if (!ValidateRobustEntryPoint(context, bufSize))
4323 {
4324 return false;
4325 }
4326
Brandon Jonesd1049182018-03-28 10:02:20 -07004327 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004328 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004329 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004330 {
4331 return false;
4332 }
4333
Brandon Jonesd1049182018-03-28 10:02:20 -07004334 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004335 {
4336 return false;
4337 }
4338
Brandon Jonesd1049182018-03-28 10:02:20 -07004339 SetRobustLengthParam(length, numParams);
4340
Geoff Langff5b2d52016-09-07 11:32:23 -04004341 return true;
4342}
4343
Jamie Madill5b772312018-03-08 20:28:32 -05004344bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004345 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004346 GLenum pname,
4347 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004348 GLsizei *length,
4349 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004350{
4351 if (!ValidateRobustEntryPoint(context, bufSize))
4352 {
4353 return false;
4354 }
4355
Brandon Jonesd1049182018-03-28 10:02:20 -07004356 GLsizei numParams = 0;
4357
4358 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004359 {
4360 return false;
4361 }
4362
Brandon Jonesd1049182018-03-28 10:02:20 -07004363 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004364 {
4365 return false;
4366 }
4367
Brandon Jonesd1049182018-03-28 10:02:20 -07004368 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004369 return true;
4370}
4371
Jamie Madill5b772312018-03-08 20:28:32 -05004372bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004373 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004374 GLenum pname,
4375 GLsizei bufSize,
4376 GLsizei *length,
4377 GLint64 *params)
4378{
Brandon Jonesd1049182018-03-28 10:02:20 -07004379 GLsizei numParams = 0;
4380
Geoff Langebebe1c2016-10-14 12:01:31 -04004381 if (!ValidateRobustEntryPoint(context, bufSize))
4382 {
4383 return false;
4384 }
4385
Brandon Jonesd1049182018-03-28 10:02:20 -07004386 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004387 {
4388 return false;
4389 }
4390
Brandon Jonesd1049182018-03-28 10:02:20 -07004391 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004392 {
4393 return false;
4394 }
4395
Brandon Jonesd1049182018-03-28 10:02:20 -07004396 SetRobustLengthParam(length, numParams);
4397
Geoff Langff5b2d52016-09-07 11:32:23 -04004398 return true;
4399}
4400
Jamie Madill5b772312018-03-08 20:28:32 -05004401bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004402{
4403 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004404 if (numParams)
4405 {
4406 *numParams = 1;
4407 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004408
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004409 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
4410 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
4411 ? GetValidProgramNoResolve(context, program)
4412 : GetValidProgram(context, program);
Geoff Langff5b2d52016-09-07 11:32:23 -04004413 if (!programObject)
4414 {
4415 return false;
4416 }
4417
4418 switch (pname)
4419 {
4420 case GL_DELETE_STATUS:
4421 case GL_LINK_STATUS:
4422 case GL_VALIDATE_STATUS:
4423 case GL_INFO_LOG_LENGTH:
4424 case GL_ATTACHED_SHADERS:
4425 case GL_ACTIVE_ATTRIBUTES:
4426 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4427 case GL_ACTIVE_UNIFORMS:
4428 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4429 break;
4430
4431 case GL_PROGRAM_BINARY_LENGTH:
4432 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004434 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4435 "requires GL_OES_get_program_binary or "
4436 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004437 return false;
4438 }
4439 break;
4440
4441 case GL_ACTIVE_UNIFORM_BLOCKS:
4442 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4443 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4444 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4445 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4446 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4447 if (context->getClientMajorVersion() < 3)
4448 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004450 return false;
4451 }
4452 break;
4453
Yunchao He61afff12017-03-14 15:34:03 +08004454 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004455 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004456 if (context->getClientVersion() < Version(3, 1))
4457 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004458 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004459 return false;
4460 }
4461 break;
4462
Jiawei Shao6ae51612018-02-23 14:03:25 +08004463 case GL_COMPUTE_WORK_GROUP_SIZE:
4464 if (context->getClientVersion() < Version(3, 1))
4465 {
4466 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4467 return false;
4468 }
4469
4470 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4471 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4472 // program which has not been linked successfully, or which does not contain objects to
4473 // form a compute shader.
4474 if (!programObject->isLinked())
4475 {
4476 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4477 return false;
4478 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004479 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004480 {
4481 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4482 return false;
4483 }
4484 break;
4485
Jiawei Shao447bfac2018-03-14 14:23:40 +08004486 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4487 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4488 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4489 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4490 if (!context->getExtensions().geometryShader)
4491 {
4492 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4493 return false;
4494 }
4495
4496 // [EXT_geometry_shader] Chapter 7.12
4497 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4498 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4499 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4500 // successfully, or which does not contain objects to form a geometry shader.
4501 if (!programObject->isLinked())
4502 {
4503 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4504 return false;
4505 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004506 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004507 {
4508 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4509 return false;
4510 }
4511 break;
4512
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004513 case GL_COMPLETION_STATUS_KHR:
4514 if (!context->getExtensions().parallelShaderCompile)
4515 {
4516 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
4517 return false;
4518 }
4519 break;
4520
Geoff Langff5b2d52016-09-07 11:32:23 -04004521 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004523 return false;
4524 }
4525
4526 return true;
4527}
4528
4529bool ValidateGetProgramivRobustANGLE(Context *context,
4530 GLuint program,
4531 GLenum pname,
4532 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004533 GLsizei *length,
4534 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004535{
4536 if (!ValidateRobustEntryPoint(context, bufSize))
4537 {
4538 return false;
4539 }
4540
Brandon Jonesd1049182018-03-28 10:02:20 -07004541 GLsizei numParams = 0;
4542
4543 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004544 {
4545 return false;
4546 }
4547
Brandon Jonesd1049182018-03-28 10:02:20 -07004548 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004549 {
4550 return false;
4551 }
4552
Brandon Jonesd1049182018-03-28 10:02:20 -07004553 SetRobustLengthParam(length, numParams);
4554
Geoff Langff5b2d52016-09-07 11:32:23 -04004555 return true;
4556}
4557
Geoff Lang740d9022016-10-07 11:20:52 -04004558bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4559 GLenum target,
4560 GLenum pname,
4561 GLsizei bufSize,
4562 GLsizei *length,
4563 GLint *params)
4564{
4565 if (!ValidateRobustEntryPoint(context, bufSize))
4566 {
4567 return false;
4568 }
4569
Brandon Jonesd1049182018-03-28 10:02:20 -07004570 GLsizei numParams = 0;
4571
4572 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004573 {
4574 return false;
4575 }
4576
Brandon Jonesd1049182018-03-28 10:02:20 -07004577 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004578 {
4579 return false;
4580 }
4581
Brandon Jonesd1049182018-03-28 10:02:20 -07004582 SetRobustLengthParam(length, numParams);
4583
Geoff Lang740d9022016-10-07 11:20:52 -04004584 return true;
4585}
4586
Geoff Langd7d0ed32016-10-07 11:33:51 -04004587bool ValidateGetShaderivRobustANGLE(Context *context,
4588 GLuint shader,
4589 GLenum pname,
4590 GLsizei bufSize,
4591 GLsizei *length,
4592 GLint *params)
4593{
4594 if (!ValidateRobustEntryPoint(context, bufSize))
4595 {
4596 return false;
4597 }
4598
Brandon Jonesd1049182018-03-28 10:02:20 -07004599 GLsizei numParams = 0;
4600
4601 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004602 {
4603 return false;
4604 }
4605
Brandon Jonesd1049182018-03-28 10:02:20 -07004606 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004607 {
4608 return false;
4609 }
4610
Brandon Jonesd1049182018-03-28 10:02:20 -07004611 SetRobustLengthParam(length, numParams);
4612
Geoff Langd7d0ed32016-10-07 11:33:51 -04004613 return true;
4614}
4615
Geoff Langc1984ed2016-10-07 12:41:00 -04004616bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004617 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004618 GLenum pname,
4619 GLsizei bufSize,
4620 GLsizei *length,
4621 GLfloat *params)
4622{
4623 if (!ValidateRobustEntryPoint(context, bufSize))
4624 {
4625 return false;
4626 }
4627
Brandon Jonesd1049182018-03-28 10:02:20 -07004628 GLsizei numParams = 0;
4629
4630 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004631 {
4632 return false;
4633 }
4634
Brandon Jonesd1049182018-03-28 10:02:20 -07004635 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004636 {
4637 return false;
4638 }
4639
Brandon Jonesd1049182018-03-28 10:02:20 -07004640 SetRobustLengthParam(length, numParams);
4641
Geoff Langc1984ed2016-10-07 12:41:00 -04004642 return true;
4643}
4644
Geoff Langc1984ed2016-10-07 12:41:00 -04004645bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004646 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004647 GLenum pname,
4648 GLsizei bufSize,
4649 GLsizei *length,
4650 GLint *params)
4651{
Brandon Jonesd1049182018-03-28 10:02:20 -07004652
Geoff Langc1984ed2016-10-07 12:41:00 -04004653 if (!ValidateRobustEntryPoint(context, bufSize))
4654 {
4655 return false;
4656 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004657 GLsizei numParams = 0;
4658 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004659 {
4660 return false;
4661 }
4662
Brandon Jonesd1049182018-03-28 10:02:20 -07004663 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004664 {
4665 return false;
4666 }
4667
Brandon Jonesd1049182018-03-28 10:02:20 -07004668 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004669 return true;
4670}
4671
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004672bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4673 TextureType target,
4674 GLenum pname,
4675 GLsizei bufSize,
4676 GLsizei *length,
4677 GLint *params)
4678{
4679 UNIMPLEMENTED();
4680 return false;
4681}
4682
4683bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4684 TextureType target,
4685 GLenum pname,
4686 GLsizei bufSize,
4687 GLsizei *length,
4688 GLuint *params)
4689{
4690 UNIMPLEMENTED();
4691 return false;
4692}
4693
Geoff Langc1984ed2016-10-07 12:41:00 -04004694bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004695 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004696 GLenum pname,
4697 GLsizei bufSize,
4698 const GLfloat *params)
4699{
4700 if (!ValidateRobustEntryPoint(context, bufSize))
4701 {
4702 return false;
4703 }
4704
4705 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4706}
4707
Geoff Langc1984ed2016-10-07 12:41:00 -04004708bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004709 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004710 GLenum pname,
4711 GLsizei bufSize,
4712 const GLint *params)
4713{
4714 if (!ValidateRobustEntryPoint(context, bufSize))
4715 {
4716 return false;
4717 }
4718
4719 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4720}
4721
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004722bool ValidateTexParameterIivRobustANGLE(Context *context,
4723 TextureType target,
4724 GLenum pname,
4725 GLsizei bufSize,
4726 const GLint *params)
4727{
4728 UNIMPLEMENTED();
4729 return false;
4730}
4731
4732bool ValidateTexParameterIuivRobustANGLE(Context *context,
4733 TextureType target,
4734 GLenum pname,
4735 GLsizei bufSize,
4736 const GLuint *params)
4737{
4738 UNIMPLEMENTED();
4739 return false;
4740}
4741
Geoff Langc1984ed2016-10-07 12:41:00 -04004742bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4743 GLuint sampler,
4744 GLenum pname,
4745 GLuint bufSize,
4746 GLsizei *length,
4747 GLfloat *params)
4748{
4749 if (!ValidateRobustEntryPoint(context, bufSize))
4750 {
4751 return false;
4752 }
4753
Brandon Jonesd1049182018-03-28 10:02:20 -07004754 GLsizei numParams = 0;
4755
4756 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004757 {
4758 return false;
4759 }
4760
Brandon Jonesd1049182018-03-28 10:02:20 -07004761 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004762 {
4763 return false;
4764 }
4765
Brandon Jonesd1049182018-03-28 10:02:20 -07004766 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004767 return true;
4768}
4769
Geoff Langc1984ed2016-10-07 12:41:00 -04004770bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4771 GLuint sampler,
4772 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004773 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004774 GLsizei *length,
4775 GLint *params)
4776{
4777 if (!ValidateRobustEntryPoint(context, bufSize))
4778 {
4779 return false;
4780 }
4781
Brandon Jonesd1049182018-03-28 10:02:20 -07004782 GLsizei numParams = 0;
4783
4784 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004785 {
4786 return false;
4787 }
4788
Brandon Jonesd1049182018-03-28 10:02:20 -07004789 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004790 {
4791 return false;
4792 }
4793
Brandon Jonesd1049182018-03-28 10:02:20 -07004794 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004795 return true;
4796}
4797
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004798bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4799 GLuint sampler,
4800 GLenum pname,
4801 GLsizei bufSize,
4802 GLsizei *length,
4803 GLint *params)
4804{
4805 UNIMPLEMENTED();
4806 return false;
4807}
4808
4809bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4810 GLuint sampler,
4811 GLenum pname,
4812 GLsizei bufSize,
4813 GLsizei *length,
4814 GLuint *params)
4815{
4816 UNIMPLEMENTED();
4817 return false;
4818}
4819
Geoff Langc1984ed2016-10-07 12:41:00 -04004820bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4821 GLuint sampler,
4822 GLenum pname,
4823 GLsizei bufSize,
4824 const GLfloat *params)
4825{
4826 if (!ValidateRobustEntryPoint(context, bufSize))
4827 {
4828 return false;
4829 }
4830
4831 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4832}
4833
Geoff Langc1984ed2016-10-07 12:41:00 -04004834bool ValidateSamplerParameterivRobustANGLE(Context *context,
4835 GLuint sampler,
4836 GLenum pname,
4837 GLsizei bufSize,
4838 const GLint *params)
4839{
4840 if (!ValidateRobustEntryPoint(context, bufSize))
4841 {
4842 return false;
4843 }
4844
4845 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4846}
4847
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004848bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4849 GLuint sampler,
4850 GLenum pname,
4851 GLsizei bufSize,
4852 const GLint *param)
4853{
4854 UNIMPLEMENTED();
4855 return false;
4856}
4857
4858bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4859 GLuint sampler,
4860 GLenum pname,
4861 GLsizei bufSize,
4862 const GLuint *param)
4863{
4864 UNIMPLEMENTED();
4865 return false;
4866}
4867
Geoff Lang0b031062016-10-13 14:30:04 -04004868bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4869 GLuint index,
4870 GLenum pname,
4871 GLsizei bufSize,
4872 GLsizei *length,
4873 GLfloat *params)
4874{
4875 if (!ValidateRobustEntryPoint(context, bufSize))
4876 {
4877 return false;
4878 }
4879
Brandon Jonesd1049182018-03-28 10:02:20 -07004880 GLsizei writeLength = 0;
4881
4882 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004883 {
4884 return false;
4885 }
4886
Brandon Jonesd1049182018-03-28 10:02:20 -07004887 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004888 {
4889 return false;
4890 }
4891
Brandon Jonesd1049182018-03-28 10:02:20 -07004892 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004893 return true;
4894}
4895
Geoff Lang0b031062016-10-13 14:30:04 -04004896bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4897 GLuint index,
4898 GLenum pname,
4899 GLsizei bufSize,
4900 GLsizei *length,
4901 GLint *params)
4902{
4903 if (!ValidateRobustEntryPoint(context, bufSize))
4904 {
4905 return false;
4906 }
4907
Brandon Jonesd1049182018-03-28 10:02:20 -07004908 GLsizei writeLength = 0;
4909
4910 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004911 {
4912 return false;
4913 }
4914
Brandon Jonesd1049182018-03-28 10:02:20 -07004915 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004916 {
4917 return false;
4918 }
4919
Brandon Jonesd1049182018-03-28 10:02:20 -07004920 SetRobustLengthParam(length, writeLength);
4921
Geoff Lang0b031062016-10-13 14:30:04 -04004922 return true;
4923}
4924
Geoff Lang0b031062016-10-13 14:30:04 -04004925bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4926 GLuint index,
4927 GLenum pname,
4928 GLsizei bufSize,
4929 GLsizei *length,
4930 void **pointer)
4931{
4932 if (!ValidateRobustEntryPoint(context, bufSize))
4933 {
4934 return false;
4935 }
4936
Brandon Jonesd1049182018-03-28 10:02:20 -07004937 GLsizei writeLength = 0;
4938
4939 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004940 {
4941 return false;
4942 }
4943
Brandon Jonesd1049182018-03-28 10:02:20 -07004944 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004945 {
4946 return false;
4947 }
4948
Brandon Jonesd1049182018-03-28 10:02:20 -07004949 SetRobustLengthParam(length, writeLength);
4950
Geoff Lang0b031062016-10-13 14:30:04 -04004951 return true;
4952}
4953
Geoff Lang0b031062016-10-13 14:30:04 -04004954bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4955 GLuint index,
4956 GLenum pname,
4957 GLsizei bufSize,
4958 GLsizei *length,
4959 GLint *params)
4960{
4961 if (!ValidateRobustEntryPoint(context, bufSize))
4962 {
4963 return false;
4964 }
4965
Brandon Jonesd1049182018-03-28 10:02:20 -07004966 GLsizei writeLength = 0;
4967
4968 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004969 {
4970 return false;
4971 }
4972
Brandon Jonesd1049182018-03-28 10:02:20 -07004973 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004974 {
4975 return false;
4976 }
4977
Brandon Jonesd1049182018-03-28 10:02:20 -07004978 SetRobustLengthParam(length, writeLength);
4979
Geoff Lang0b031062016-10-13 14:30:04 -04004980 return true;
4981}
4982
Geoff Lang0b031062016-10-13 14:30:04 -04004983bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4984 GLuint index,
4985 GLenum pname,
4986 GLsizei bufSize,
4987 GLsizei *length,
4988 GLuint *params)
4989{
4990 if (!ValidateRobustEntryPoint(context, bufSize))
4991 {
4992 return false;
4993 }
4994
Brandon Jonesd1049182018-03-28 10:02:20 -07004995 GLsizei writeLength = 0;
4996
4997 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004998 {
4999 return false;
5000 }
5001
Brandon Jonesd1049182018-03-28 10:02:20 -07005002 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005003 {
5004 return false;
5005 }
5006
Brandon Jonesd1049182018-03-28 10:02:20 -07005007 SetRobustLengthParam(length, writeLength);
5008
Geoff Lang0b031062016-10-13 14:30:04 -04005009 return true;
5010}
5011
Geoff Lang6899b872016-10-14 11:30:13 -04005012bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5013 GLuint program,
5014 GLuint uniformBlockIndex,
5015 GLenum pname,
5016 GLsizei bufSize,
5017 GLsizei *length,
5018 GLint *params)
5019{
5020 if (!ValidateRobustEntryPoint(context, bufSize))
5021 {
5022 return false;
5023 }
5024
Brandon Jonesd1049182018-03-28 10:02:20 -07005025 GLsizei writeLength = 0;
5026
5027 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5028 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005029 {
5030 return false;
5031 }
5032
Brandon Jonesd1049182018-03-28 10:02:20 -07005033 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005034 {
5035 return false;
5036 }
5037
Brandon Jonesd1049182018-03-28 10:02:20 -07005038 SetRobustLengthParam(length, writeLength);
5039
Geoff Lang6899b872016-10-14 11:30:13 -04005040 return true;
5041}
5042
Brandon Jones416aaf92018-04-10 08:10:16 -07005043bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005044 GLenum target,
5045 GLenum internalformat,
5046 GLenum pname,
5047 GLsizei bufSize,
5048 GLsizei *length,
5049 GLint *params)
5050{
5051 if (!ValidateRobustEntryPoint(context, bufSize))
5052 {
5053 return false;
5054 }
5055
Brandon Jonesd1049182018-03-28 10:02:20 -07005056 GLsizei numParams = 0;
5057
5058 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5059 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005060 {
5061 return false;
5062 }
5063
Brandon Jonesd1049182018-03-28 10:02:20 -07005064 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005065 {
5066 return false;
5067 }
5068
Brandon Jonesd1049182018-03-28 10:02:20 -07005069 SetRobustLengthParam(length, numParams);
5070
Geoff Lang0a9661f2016-10-20 10:59:20 -07005071 return true;
5072}
5073
Jamie Madill5b772312018-03-08 20:28:32 -05005074bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005075 GLuint attribIndex,
5076 GLint size,
5077 GLenum type,
5078 GLboolean pureInteger)
5079{
5080 const Caps &caps = context->getCaps();
5081 if (attribIndex >= caps.maxVertexAttributes)
5082 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005083 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005084 return false;
5085 }
5086
5087 if (size < 1 || size > 4)
5088 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005089 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005090 return false;
Shao80957d92017-02-20 21:25:59 +08005091 }
5092
5093 switch (type)
5094 {
5095 case GL_BYTE:
5096 case GL_UNSIGNED_BYTE:
5097 case GL_SHORT:
5098 case GL_UNSIGNED_SHORT:
5099 break;
5100
5101 case GL_INT:
5102 case GL_UNSIGNED_INT:
5103 if (context->getClientMajorVersion() < 3)
5104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005105 context->handleError(InvalidEnum()
5106 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005107 return false;
5108 }
5109 break;
5110
5111 case GL_FIXED:
5112 case GL_FLOAT:
5113 if (pureInteger)
5114 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005115 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005116 return false;
5117 }
5118 break;
5119
5120 case GL_HALF_FLOAT:
5121 if (context->getClientMajorVersion() < 3)
5122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005123 context->handleError(InvalidEnum()
5124 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005125 return false;
5126 }
5127 if (pureInteger)
5128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005130 return false;
5131 }
5132 break;
5133
5134 case GL_INT_2_10_10_10_REV:
5135 case GL_UNSIGNED_INT_2_10_10_10_REV:
5136 if (context->getClientMajorVersion() < 3)
5137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005138 context->handleError(InvalidEnum()
5139 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005140 return false;
5141 }
5142 if (pureInteger)
5143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005144 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005145 return false;
5146 }
5147 if (size != 4)
5148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005149 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5150 "UNSIGNED_INT_2_10_10_10_REV and "
5151 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005152 return false;
5153 }
5154 break;
5155
5156 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005157 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005158 return false;
5159 }
5160
5161 return true;
5162}
5163
Geoff Lang76e65652017-03-27 14:58:02 -04005164// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5165// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5166// specified clear value and the type of a buffer that is being cleared generates an
5167// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005168bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005169 GLint drawbuffer,
5170 const GLenum *validComponentTypes,
5171 size_t validComponentTypeCount)
5172{
5173 const FramebufferAttachment *attachment =
5174 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5175 if (attachment)
5176 {
5177 GLenum componentType = attachment->getFormat().info->componentType;
5178 const GLenum *end = validComponentTypes + validComponentTypeCount;
5179 if (std::find(validComponentTypes, end, componentType) == end)
5180 {
5181 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005182 InvalidOperation()
5183 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005184 return false;
5185 }
5186 }
5187
5188 return true;
5189}
5190
Jamie Madill5b772312018-03-08 20:28:32 -05005191bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005192{
5193 if (!ValidateRobustEntryPoint(context, dataSize))
5194 {
5195 return false;
5196 }
5197
Jamie Madill43da7c42018-08-01 11:34:49 -04005198 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005199 if (pixelUnpackBuffer == nullptr)
5200 {
5201 if (dataSize < imageSize)
5202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005203 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005204 }
5205 }
5206 return true;
5207}
5208
Jamie Madill5b772312018-03-08 20:28:32 -05005209bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005210 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005211 GLenum pname,
5212 bool pointerVersion,
5213 GLsizei *numParams)
5214{
5215 if (numParams)
5216 {
5217 *numParams = 0;
5218 }
5219
Corentin Walleze4477002017-12-01 14:39:58 -05005220 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005222 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005223 return false;
5224 }
5225
5226 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5227 if (!buffer)
5228 {
5229 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005231 return false;
5232 }
5233
5234 const Extensions &extensions = context->getExtensions();
5235
5236 switch (pname)
5237 {
5238 case GL_BUFFER_USAGE:
5239 case GL_BUFFER_SIZE:
5240 break;
5241
5242 case GL_BUFFER_ACCESS_OES:
5243 if (!extensions.mapBuffer)
5244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005245 context->handleError(InvalidEnum()
5246 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005247 return false;
5248 }
5249 break;
5250
5251 case GL_BUFFER_MAPPED:
5252 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5253 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5254 !extensions.mapBufferRange)
5255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005256 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5257 "GL_OES_mapbuffer or "
5258 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005259 return false;
5260 }
5261 break;
5262
5263 case GL_BUFFER_MAP_POINTER:
5264 if (!pointerVersion)
5265 {
5266 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005267 InvalidEnum()
5268 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005269 return false;
5270 }
5271 break;
5272
5273 case GL_BUFFER_ACCESS_FLAGS:
5274 case GL_BUFFER_MAP_OFFSET:
5275 case GL_BUFFER_MAP_LENGTH:
5276 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005278 context->handleError(InvalidEnum()
5279 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005280 return false;
5281 }
5282 break;
5283
5284 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005285 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005286 return false;
5287 }
5288
5289 // All buffer parameter queries return one value.
5290 if (numParams)
5291 {
5292 *numParams = 1;
5293 }
5294
5295 return true;
5296}
5297
5298bool ValidateGetRenderbufferParameterivBase(Context *context,
5299 GLenum target,
5300 GLenum pname,
5301 GLsizei *length)
5302{
5303 if (length)
5304 {
5305 *length = 0;
5306 }
5307
5308 if (target != GL_RENDERBUFFER)
5309 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005310 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005311 return false;
5312 }
5313
5314 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5315 if (renderbuffer == nullptr)
5316 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005317 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005318 return false;
5319 }
5320
5321 switch (pname)
5322 {
5323 case GL_RENDERBUFFER_WIDTH:
5324 case GL_RENDERBUFFER_HEIGHT:
5325 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5326 case GL_RENDERBUFFER_RED_SIZE:
5327 case GL_RENDERBUFFER_GREEN_SIZE:
5328 case GL_RENDERBUFFER_BLUE_SIZE:
5329 case GL_RENDERBUFFER_ALPHA_SIZE:
5330 case GL_RENDERBUFFER_DEPTH_SIZE:
5331 case GL_RENDERBUFFER_STENCIL_SIZE:
5332 break;
5333
5334 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5335 if (!context->getExtensions().framebufferMultisample)
5336 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005337 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005338 return false;
5339 }
5340 break;
5341
5342 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005344 return false;
5345 }
5346
5347 if (length)
5348 {
5349 *length = 1;
5350 }
5351 return true;
5352}
5353
5354bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5355{
5356 if (length)
5357 {
5358 *length = 0;
5359 }
5360
5361 if (GetValidShader(context, shader) == nullptr)
5362 {
5363 return false;
5364 }
5365
5366 switch (pname)
5367 {
5368 case GL_SHADER_TYPE:
5369 case GL_DELETE_STATUS:
5370 case GL_COMPILE_STATUS:
5371 case GL_INFO_LOG_LENGTH:
5372 case GL_SHADER_SOURCE_LENGTH:
5373 break;
5374
5375 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5376 if (!context->getExtensions().translatedShaderSource)
5377 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005378 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005379 return false;
5380 }
5381 break;
5382
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005383 case GL_COMPLETION_STATUS_KHR:
5384 if (!context->getExtensions().parallelShaderCompile)
5385 {
5386 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
5387 return false;
5388 }
5389 break;
5390
Jamie Madillbe849e42017-05-02 15:49:00 -04005391 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395
5396 if (length)
5397 {
5398 *length = 1;
5399 }
5400 return true;
5401}
5402
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005403bool ValidateGetTexParameterBase(Context *context,
5404 TextureType target,
5405 GLenum pname,
5406 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005407{
5408 if (length)
5409 {
5410 *length = 0;
5411 }
5412
5413 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5414 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005415 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005416 return false;
5417 }
5418
5419 if (context->getTargetTexture(target) == nullptr)
5420 {
5421 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005422 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005423 return false;
5424 }
5425
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005426 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5427 {
5428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5429 return false;
5430 }
5431
Jamie Madillbe849e42017-05-02 15:49:00 -04005432 switch (pname)
5433 {
5434 case GL_TEXTURE_MAG_FILTER:
5435 case GL_TEXTURE_MIN_FILTER:
5436 case GL_TEXTURE_WRAP_S:
5437 case GL_TEXTURE_WRAP_T:
5438 break;
5439
5440 case GL_TEXTURE_USAGE_ANGLE:
5441 if (!context->getExtensions().textureUsage)
5442 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005443 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005444 return false;
5445 }
5446 break;
5447
5448 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005449 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005450 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005451 return false;
5452 }
5453 break;
5454
5455 case GL_TEXTURE_IMMUTABLE_FORMAT:
5456 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5457 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005458 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005459 return false;
5460 }
5461 break;
5462
5463 case GL_TEXTURE_WRAP_R:
5464 case GL_TEXTURE_IMMUTABLE_LEVELS:
5465 case GL_TEXTURE_SWIZZLE_R:
5466 case GL_TEXTURE_SWIZZLE_G:
5467 case GL_TEXTURE_SWIZZLE_B:
5468 case GL_TEXTURE_SWIZZLE_A:
5469 case GL_TEXTURE_BASE_LEVEL:
5470 case GL_TEXTURE_MAX_LEVEL:
5471 case GL_TEXTURE_MIN_LOD:
5472 case GL_TEXTURE_MAX_LOD:
5473 case GL_TEXTURE_COMPARE_MODE:
5474 case GL_TEXTURE_COMPARE_FUNC:
5475 if (context->getClientMajorVersion() < 3)
5476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005477 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005478 return false;
5479 }
5480 break;
5481
5482 case GL_TEXTURE_SRGB_DECODE_EXT:
5483 if (!context->getExtensions().textureSRGBDecode)
5484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005485 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005486 return false;
5487 }
5488 break;
5489
Yunchao Hebacaa712018-01-30 14:01:39 +08005490 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5491 if (context->getClientVersion() < Version(3, 1))
5492 {
5493 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5494 return false;
5495 }
5496 break;
5497
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005498 case GL_GENERATE_MIPMAP:
5499 case GL_TEXTURE_CROP_RECT_OES:
5500 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5501 // after GL_OES_draw_texture functionality implemented
5502 if (context->getClientMajorVersion() > 1)
5503 {
5504 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5505 return false;
5506 }
5507 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005508 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005509 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005510 return false;
5511 }
5512
5513 if (length)
5514 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005515 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005516 }
5517 return true;
5518}
5519
5520bool ValidateGetVertexAttribBase(Context *context,
5521 GLuint index,
5522 GLenum pname,
5523 GLsizei *length,
5524 bool pointer,
5525 bool pureIntegerEntryPoint)
5526{
5527 if (length)
5528 {
5529 *length = 0;
5530 }
5531
5532 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005534 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005535 return false;
5536 }
5537
5538 if (index >= context->getCaps().maxVertexAttributes)
5539 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005540 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005541 return false;
5542 }
5543
5544 if (pointer)
5545 {
5546 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5547 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005548 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005549 return false;
5550 }
5551 }
5552 else
5553 {
5554 switch (pname)
5555 {
5556 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5557 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5558 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5559 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5560 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5561 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5562 case GL_CURRENT_VERTEX_ATTRIB:
5563 break;
5564
5565 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5566 static_assert(
5567 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5568 "ANGLE extension enums not equal to GL enums.");
5569 if (context->getClientMajorVersion() < 3 &&
5570 !context->getExtensions().instancedArrays)
5571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005572 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5573 "requires OpenGL ES 3.0 or "
5574 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005575 return false;
5576 }
5577 break;
5578
5579 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5580 if (context->getClientMajorVersion() < 3)
5581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005582 context->handleError(
5583 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005584 return false;
5585 }
5586 break;
5587
5588 case GL_VERTEX_ATTRIB_BINDING:
5589 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5590 if (context->getClientVersion() < ES_3_1)
5591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005592 context->handleError(InvalidEnum()
5593 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005594 return false;
5595 }
5596 break;
5597
5598 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005599 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005600 return false;
5601 }
5602 }
5603
5604 if (length)
5605 {
5606 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5607 {
5608 *length = 4;
5609 }
5610 else
5611 {
5612 *length = 1;
5613 }
5614 }
5615
5616 return true;
5617}
5618
Jamie Madill4928b7c2017-06-20 12:57:39 -04005619bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005620 GLint x,
5621 GLint y,
5622 GLsizei width,
5623 GLsizei height,
5624 GLenum format,
5625 GLenum type,
5626 GLsizei bufSize,
5627 GLsizei *length,
5628 GLsizei *columns,
5629 GLsizei *rows,
5630 void *pixels)
5631{
5632 if (length != nullptr)
5633 {
5634 *length = 0;
5635 }
5636 if (rows != nullptr)
5637 {
5638 *rows = 0;
5639 }
5640 if (columns != nullptr)
5641 {
5642 *columns = 0;
5643 }
5644
5645 if (width < 0 || height < 0)
5646 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005647 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005648 return false;
5649 }
5650
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005651 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005652
Jamie Madill427064d2018-04-13 16:20:34 -04005653 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005654 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005655 return false;
5656 }
5657
Jamie Madille98b1b52018-03-08 09:47:23 -05005658 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005659 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 return false;
5661 }
5662
Jamie Madill690c8eb2018-03-12 15:20:03 -04005663 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005664 ASSERT(framebuffer);
5665
5666 if (framebuffer->getReadBufferState() == GL_NONE)
5667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005669 return false;
5670 }
5671
5672 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5673 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5674 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5675 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5676 // situation is an application error that would lead to a crash in ANGLE.
5677 if (readBuffer == nullptr)
5678 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005679 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005680 return false;
5681 }
5682
Martin Radev28031682017-07-28 14:47:56 +03005683 // ANGLE_multiview, Revision 1:
5684 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005685 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5686 // in the current read framebuffer is more than one.
5687 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005688 {
5689 context->handleError(InvalidFramebufferOperation()
5690 << "Attempting to read from a multi-view framebuffer.");
5691 return false;
5692 }
5693
Geoff Lang280ba992017-04-18 16:30:58 -04005694 if (context->getExtensions().webglCompatibility)
5695 {
5696 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5697 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5698 // and type before validating the combination of format and type. However, the
5699 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5700 // verifies that GL_INVALID_OPERATION is generated.
5701 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5702 // dEQP/WebGL.
5703 if (!ValidReadPixelsFormatEnum(context, format))
5704 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005705 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005706 return false;
5707 }
5708
5709 if (!ValidReadPixelsTypeEnum(context, type))
5710 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005711 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005712 return false;
5713 }
5714 }
5715
Jamie Madill690c8eb2018-03-12 15:20:03 -04005716 GLenum currentFormat = GL_NONE;
5717 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5718
5719 GLenum currentType = GL_NONE;
5720 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5721
Jamie Madillbe849e42017-05-02 15:49:00 -04005722 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5723
5724 bool validFormatTypeCombination =
5725 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5726
5727 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5728 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005729 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005730 return false;
5731 }
5732
5733 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005734 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005735 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5736 {
5737 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005738 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005739 return false;
5740 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005741 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5742 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5743 {
5744 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5745 return false;
5746 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005747
5748 // .. the data would be packed to the buffer object such that the memory writes required
5749 // would exceed the data store size.
5750 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005751 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005752 const auto &pack = context->getGLState().getPackState();
5753
Jamie Madillca2ff382018-07-11 09:01:17 -04005754 GLuint endByte = 0;
5755 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005756 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005757 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005758 return false;
5759 }
5760
Jamie Madillbe849e42017-05-02 15:49:00 -04005761 if (bufSize >= 0)
5762 {
5763 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5764 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005765 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005766 return false;
5767 }
5768 }
5769
5770 if (pixelPackBuffer != nullptr)
5771 {
5772 CheckedNumeric<size_t> checkedEndByte(endByte);
5773 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5774 checkedEndByte += checkedOffset;
5775
5776 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5777 {
5778 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005779 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005780 return false;
5781 }
5782 }
5783
5784 if (pixelPackBuffer == nullptr && length != nullptr)
5785 {
5786 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5787 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005789 return false;
5790 }
5791
5792 *length = static_cast<GLsizei>(endByte);
5793 }
5794
Geoff Langa953b522018-02-21 16:56:23 -05005795 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005796 angle::CheckedNumeric<int> clippedExtent(length);
5797 if (start < 0)
5798 {
5799 // "subtract" the area that is less than 0
5800 clippedExtent += start;
5801 }
5802
Geoff Langa953b522018-02-21 16:56:23 -05005803 angle::CheckedNumeric<int> readExtent = start;
5804 readExtent += length;
5805 if (!readExtent.IsValid())
5806 {
5807 return false;
5808 }
5809
5810 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005811 {
5812 // Subtract the region to the right of the read buffer
5813 clippedExtent -= (readExtent - bufferSize);
5814 }
5815
5816 if (!clippedExtent.IsValid())
5817 {
Geoff Langa953b522018-02-21 16:56:23 -05005818 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005819 }
5820
Geoff Langa953b522018-02-21 16:56:23 -05005821 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5822 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005823 };
5824
Geoff Langa953b522018-02-21 16:56:23 -05005825 GLsizei writtenColumns = 0;
5826 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5827 {
5828 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5829 return false;
5830 }
5831
5832 GLsizei writtenRows = 0;
5833 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5834 {
5835 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5836 return false;
5837 }
5838
Jamie Madillbe849e42017-05-02 15:49:00 -04005839 if (columns != nullptr)
5840 {
Geoff Langa953b522018-02-21 16:56:23 -05005841 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005842 }
5843
5844 if (rows != nullptr)
5845 {
Geoff Langa953b522018-02-21 16:56:23 -05005846 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005847 }
5848
5849 return true;
5850}
5851
5852template <typename ParamType>
5853bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005854 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005855 GLenum pname,
5856 GLsizei bufSize,
5857 const ParamType *params)
5858{
5859 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5860 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005861 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005862 return false;
5863 }
5864
5865 if (context->getTargetTexture(target) == nullptr)
5866 {
5867 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005868 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005869 return false;
5870 }
5871
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005872 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005873 if (bufSize >= 0 && bufSize < minBufSize)
5874 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005875 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005876 return false;
5877 }
5878
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005879 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5880 {
5881 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5882 return false;
5883 }
5884
Jamie Madillbe849e42017-05-02 15:49:00 -04005885 switch (pname)
5886 {
5887 case GL_TEXTURE_WRAP_R:
5888 case GL_TEXTURE_SWIZZLE_R:
5889 case GL_TEXTURE_SWIZZLE_G:
5890 case GL_TEXTURE_SWIZZLE_B:
5891 case GL_TEXTURE_SWIZZLE_A:
5892 case GL_TEXTURE_BASE_LEVEL:
5893 case GL_TEXTURE_MAX_LEVEL:
5894 case GL_TEXTURE_COMPARE_MODE:
5895 case GL_TEXTURE_COMPARE_FUNC:
5896 case GL_TEXTURE_MIN_LOD:
5897 case GL_TEXTURE_MAX_LOD:
5898 if (context->getClientMajorVersion() < 3)
5899 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005900 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005901 return false;
5902 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005903 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005904 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005905 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5906 "available without "
5907 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005908 return false;
5909 }
5910 break;
5911
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005912 case GL_GENERATE_MIPMAP:
5913 case GL_TEXTURE_CROP_RECT_OES:
5914 if (context->getClientMajorVersion() > 1)
5915 {
5916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5917 return false;
5918 }
5919 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005920 default:
5921 break;
5922 }
5923
Olli Etuahod310a432018-08-24 15:40:23 +03005924 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005925 {
5926 switch (pname)
5927 {
5928 case GL_TEXTURE_MIN_FILTER:
5929 case GL_TEXTURE_MAG_FILTER:
5930 case GL_TEXTURE_WRAP_S:
5931 case GL_TEXTURE_WRAP_T:
5932 case GL_TEXTURE_WRAP_R:
5933 case GL_TEXTURE_MIN_LOD:
5934 case GL_TEXTURE_MAX_LOD:
5935 case GL_TEXTURE_COMPARE_MODE:
5936 case GL_TEXTURE_COMPARE_FUNC:
5937 context->handleError(InvalidEnum()
5938 << "Invalid parameter for 2D multisampled textures.");
5939 return false;
5940 }
5941 }
5942
Jamie Madillbe849e42017-05-02 15:49:00 -04005943 switch (pname)
5944 {
5945 case GL_TEXTURE_WRAP_S:
5946 case GL_TEXTURE_WRAP_T:
5947 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005948 {
5949 bool restrictedWrapModes =
5950 target == TextureType::External || target == TextureType::Rectangle;
5951 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005952 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005953 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005954 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005955 }
5956 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005957
5958 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005959 {
5960 bool restrictedMinFilter =
5961 target == TextureType::External || target == TextureType::Rectangle;
5962 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005963 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005964 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005965 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005966 }
5967 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005968
5969 case GL_TEXTURE_MAG_FILTER:
5970 if (!ValidateTextureMagFilterValue(context, params))
5971 {
5972 return false;
5973 }
5974 break;
5975
5976 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005977 if (!context->getExtensions().textureUsage)
5978 {
5979 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5980 return false;
5981 }
5982
Jamie Madillbe849e42017-05-02 15:49:00 -04005983 switch (ConvertToGLenum(params[0]))
5984 {
5985 case GL_NONE:
5986 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5987 break;
5988
5989 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005990 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005991 return false;
5992 }
5993 break;
5994
5995 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005996 {
5997 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5998 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005999 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006000 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006001 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006002 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6003 }
6004 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006005
6006 case GL_TEXTURE_MIN_LOD:
6007 case GL_TEXTURE_MAX_LOD:
6008 // any value is permissible
6009 break;
6010
6011 case GL_TEXTURE_COMPARE_MODE:
6012 if (!ValidateTextureCompareModeValue(context, params))
6013 {
6014 return false;
6015 }
6016 break;
6017
6018 case GL_TEXTURE_COMPARE_FUNC:
6019 if (!ValidateTextureCompareFuncValue(context, params))
6020 {
6021 return false;
6022 }
6023 break;
6024
6025 case GL_TEXTURE_SWIZZLE_R:
6026 case GL_TEXTURE_SWIZZLE_G:
6027 case GL_TEXTURE_SWIZZLE_B:
6028 case GL_TEXTURE_SWIZZLE_A:
6029 switch (ConvertToGLenum(params[0]))
6030 {
6031 case GL_RED:
6032 case GL_GREEN:
6033 case GL_BLUE:
6034 case GL_ALPHA:
6035 case GL_ZERO:
6036 case GL_ONE:
6037 break;
6038
6039 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006040 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006041 return false;
6042 }
6043 break;
6044
6045 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006046 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006048 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006049 return false;
6050 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006051 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006052 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006053 context->handleError(InvalidOperation()
6054 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006055 return false;
6056 }
Olli Etuahod310a432018-08-24 15:40:23 +03006057 if ((target == TextureType::_2DMultisample ||
6058 target == TextureType::_2DMultisampleArray) &&
6059 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006060 {
6061 context->handleError(InvalidOperation()
6062 << "Base level must be 0 for multisampled textures.");
6063 return false;
6064 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006065 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006066 {
6067 context->handleError(InvalidOperation()
6068 << "Base level must be 0 for rectangle textures.");
6069 return false;
6070 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006071 break;
6072
6073 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006074 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006075 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006076 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006077 return false;
6078 }
6079 break;
6080
6081 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6082 if (context->getClientVersion() < Version(3, 1))
6083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006084 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006085 return false;
6086 }
6087 switch (ConvertToGLenum(params[0]))
6088 {
6089 case GL_DEPTH_COMPONENT:
6090 case GL_STENCIL_INDEX:
6091 break;
6092
6093 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006094 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006095 return false;
6096 }
6097 break;
6098
6099 case GL_TEXTURE_SRGB_DECODE_EXT:
6100 if (!ValidateTextureSRGBDecodeValue(context, params))
6101 {
6102 return false;
6103 }
6104 break;
6105
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006106 case GL_GENERATE_MIPMAP:
6107 case GL_TEXTURE_CROP_RECT_OES:
6108 if (context->getClientMajorVersion() > 1)
6109 {
6110 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6111 return false;
6112 }
6113 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006114 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006115 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006116 return false;
6117 }
6118
6119 return true;
6120}
6121
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006122template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6123template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006124
Jamie Madill5b772312018-03-08 20:28:32 -05006125bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006126{
6127 if (index >= MAX_VERTEX_ATTRIBS)
6128 {
6129 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6130 return false;
6131 }
6132
6133 return true;
6134}
6135
6136bool ValidateGetActiveUniformBlockivBase(Context *context,
6137 GLuint program,
6138 GLuint uniformBlockIndex,
6139 GLenum pname,
6140 GLsizei *length)
6141{
6142 if (length)
6143 {
6144 *length = 0;
6145 }
6146
6147 if (context->getClientMajorVersion() < 3)
6148 {
6149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6150 return false;
6151 }
6152
6153 Program *programObject = GetValidProgram(context, program);
6154 if (!programObject)
6155 {
6156 return false;
6157 }
6158
6159 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6160 {
6161 context->handleError(InvalidValue()
6162 << "uniformBlockIndex exceeds active uniform block count.");
6163 return false;
6164 }
6165
6166 switch (pname)
6167 {
6168 case GL_UNIFORM_BLOCK_BINDING:
6169 case GL_UNIFORM_BLOCK_DATA_SIZE:
6170 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6171 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6172 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6173 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6174 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6175 break;
6176
6177 default:
6178 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6179 return false;
6180 }
6181
6182 if (length)
6183 {
6184 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6185 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006186 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006187 programObject->getUniformBlockByIndex(uniformBlockIndex);
6188 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6189 }
6190 else
6191 {
6192 *length = 1;
6193 }
6194 }
6195
6196 return true;
6197}
6198
Jamie Madill9696d072017-08-26 23:19:57 -04006199template <typename ParamType>
6200bool ValidateSamplerParameterBase(Context *context,
6201 GLuint sampler,
6202 GLenum pname,
6203 GLsizei bufSize,
6204 ParamType *params)
6205{
6206 if (context->getClientMajorVersion() < 3)
6207 {
6208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6209 return false;
6210 }
6211
6212 if (!context->isSampler(sampler))
6213 {
6214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6215 return false;
6216 }
6217
6218 const GLsizei minBufSize = 1;
6219 if (bufSize >= 0 && bufSize < minBufSize)
6220 {
6221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6222 return false;
6223 }
6224
6225 switch (pname)
6226 {
6227 case GL_TEXTURE_WRAP_S:
6228 case GL_TEXTURE_WRAP_T:
6229 case GL_TEXTURE_WRAP_R:
6230 if (!ValidateTextureWrapModeValue(context, params, false))
6231 {
6232 return false;
6233 }
6234 break;
6235
6236 case GL_TEXTURE_MIN_FILTER:
6237 if (!ValidateTextureMinFilterValue(context, params, false))
6238 {
6239 return false;
6240 }
6241 break;
6242
6243 case GL_TEXTURE_MAG_FILTER:
6244 if (!ValidateTextureMagFilterValue(context, params))
6245 {
6246 return false;
6247 }
6248 break;
6249
6250 case GL_TEXTURE_MIN_LOD:
6251 case GL_TEXTURE_MAX_LOD:
6252 // any value is permissible
6253 break;
6254
6255 case GL_TEXTURE_COMPARE_MODE:
6256 if (!ValidateTextureCompareModeValue(context, params))
6257 {
6258 return false;
6259 }
6260 break;
6261
6262 case GL_TEXTURE_COMPARE_FUNC:
6263 if (!ValidateTextureCompareFuncValue(context, params))
6264 {
6265 return false;
6266 }
6267 break;
6268
6269 case GL_TEXTURE_SRGB_DECODE_EXT:
6270 if (!ValidateTextureSRGBDecodeValue(context, params))
6271 {
6272 return false;
6273 }
6274 break;
6275
Luc Ferron1b1a8642018-01-23 15:12:01 -05006276 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6277 {
6278 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6279 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6280 {
6281 return false;
6282 }
6283 }
6284 break;
6285
Jamie Madill9696d072017-08-26 23:19:57 -04006286 default:
6287 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6288 return false;
6289 }
6290
6291 return true;
6292}
6293
6294template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6295template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6296
6297bool ValidateGetSamplerParameterBase(Context *context,
6298 GLuint sampler,
6299 GLenum pname,
6300 GLsizei *length)
6301{
6302 if (length)
6303 {
6304 *length = 0;
6305 }
6306
6307 if (context->getClientMajorVersion() < 3)
6308 {
6309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6310 return false;
6311 }
6312
6313 if (!context->isSampler(sampler))
6314 {
6315 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6316 return false;
6317 }
6318
6319 switch (pname)
6320 {
6321 case GL_TEXTURE_WRAP_S:
6322 case GL_TEXTURE_WRAP_T:
6323 case GL_TEXTURE_WRAP_R:
6324 case GL_TEXTURE_MIN_FILTER:
6325 case GL_TEXTURE_MAG_FILTER:
6326 case GL_TEXTURE_MIN_LOD:
6327 case GL_TEXTURE_MAX_LOD:
6328 case GL_TEXTURE_COMPARE_MODE:
6329 case GL_TEXTURE_COMPARE_FUNC:
6330 break;
6331
Luc Ferron1b1a8642018-01-23 15:12:01 -05006332 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6333 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6334 {
6335 return false;
6336 }
6337 break;
6338
Jamie Madill9696d072017-08-26 23:19:57 -04006339 case GL_TEXTURE_SRGB_DECODE_EXT:
6340 if (!context->getExtensions().textureSRGBDecode)
6341 {
6342 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6343 return false;
6344 }
6345 break;
6346
6347 default:
6348 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6349 return false;
6350 }
6351
6352 if (length)
6353 {
6354 *length = 1;
6355 }
6356 return true;
6357}
6358
6359bool ValidateGetInternalFormativBase(Context *context,
6360 GLenum target,
6361 GLenum internalformat,
6362 GLenum pname,
6363 GLsizei bufSize,
6364 GLsizei *numParams)
6365{
6366 if (numParams)
6367 {
6368 *numParams = 0;
6369 }
6370
6371 if (context->getClientMajorVersion() < 3)
6372 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006373 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006374 return false;
6375 }
6376
6377 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006378 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006379 {
6380 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6381 return false;
6382 }
6383
6384 switch (target)
6385 {
6386 case GL_RENDERBUFFER:
6387 break;
6388
6389 case GL_TEXTURE_2D_MULTISAMPLE:
6390 if (context->getClientVersion() < ES_3_1)
6391 {
Olli Etuahod310a432018-08-24 15:40:23 +03006392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureTargetRequiresES31);
Jamie Madill9696d072017-08-26 23:19:57 -04006393 return false;
6394 }
6395 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006396 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6397 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006398 {
6399 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
6400 return false;
6401 }
6402 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006403 default:
6404 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6405 return false;
6406 }
6407
6408 if (bufSize < 0)
6409 {
6410 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6411 return false;
6412 }
6413
6414 GLsizei maxWriteParams = 0;
6415 switch (pname)
6416 {
6417 case GL_NUM_SAMPLE_COUNTS:
6418 maxWriteParams = 1;
6419 break;
6420
6421 case GL_SAMPLES:
6422 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6423 break;
6424
6425 default:
6426 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6427 return false;
6428 }
6429
6430 if (numParams)
6431 {
6432 // glGetInternalFormativ will not overflow bufSize
6433 *numParams = std::min(bufSize, maxWriteParams);
6434 }
6435
6436 return true;
6437}
6438
Jamie Madille98b1b52018-03-08 09:47:23 -05006439bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6440{
Jamie Madill427064d2018-04-13 16:20:34 -04006441 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006442 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03006443 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006444 return false;
6445 }
6446 return true;
6447}
6448
Lingfeng Yang038dd532018-03-29 17:31:52 -07006449bool ValidateMultitextureUnit(Context *context, GLenum texture)
6450{
6451 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6452 {
6453 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6454 return false;
6455 }
6456 return true;
6457}
6458
Olli Etuahod310a432018-08-24 15:40:23 +03006459bool ValidateTexStorageMultisample(Context *context,
6460 TextureType target,
6461 GLsizei samples,
6462 GLint internalFormat,
6463 GLsizei width,
6464 GLsizei height)
6465{
6466 const Caps &caps = context->getCaps();
6467 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6468 static_cast<GLuint>(height) > caps.max2DTextureSize)
6469 {
6470 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureWidthOrHeightOutOfRange);
6471 return false;
6472 }
6473
6474 if (samples == 0)
6475 {
6476 ANGLE_VALIDATION_ERR(context, InvalidValue(), SamplesZero);
6477 return false;
6478 }
6479
6480 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6481 if (!formatCaps.textureAttachment)
6482 {
6483 ANGLE_VALIDATION_ERR(context, InvalidEnum(), RenderableInternalFormat);
6484 return false;
6485 }
6486
6487 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6488 // is one of the unsized base internalformats listed in table 8.11.
6489 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6490 if (formatInfo.internalFormat == GL_NONE)
6491 {
6492 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnsizedInternalFormatUnsupported);
6493 return false;
6494 }
6495
6496 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6497 {
6498 ANGLE_VALIDATION_ERR(context, InvalidOperation(), SamplesOutOfRange);
6499 return false;
6500 }
6501
6502 Texture *texture = context->getTargetTexture(target);
6503 if (!texture || texture->id() == 0)
6504 {
6505 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ZeroBoundToTarget);
6506 return false;
6507 }
6508
6509 if (texture->getImmutableFormat())
6510 {
6511 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ImmutableTextureBound);
6512 return false;
6513 }
6514 return true;
6515}
6516
Jamie Madillc29968b2016-01-20 11:17:23 -05006517} // namespace gl