blob: 2650fbcb2a168688c3e280546297b37dfb09d150 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Lingfeng Yangf97641c2018-06-21 19:22:45 -070025#include "libANGLE/queryutils.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040026#include "libANGLE/validationES2.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29#include "common/mathutil.h"
30#include "common/utilities.h"
31
Jamie Madille2e406c2016-06-02 13:04:10 -040032using namespace angle;
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034namespace gl
35{
Jamie Madill1ca74672015-07-21 15:14:11 -040036namespace
37{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050038bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
39{
40 // List of compressed format that require that the texture size is smaller than or a multiple of
41 // the compressed block size.
42 switch (internalFormat)
43 {
44 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
46 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
47 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
48 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
52 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
53 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59 return true;
jchen10a99ed552017-09-22 08:10:32 +080060
Luc Ferron9dbaeba2018-02-01 07:26:59 -050061 default:
62 return false;
63 }
64}
65bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
66{
67 // Compressed sub textures have additional formats that requires exact size.
68 // ES 3.1, Section 8.7, Page 171
69 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
70 IsETC2EACFormat(internalFormat);
71}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030072
73bool DifferenceCanOverflow(GLint a, GLint b)
74{
75 CheckedNumeric<GLint> checkedA(a);
76 checkedA -= b;
77 // Use negation to make sure that the difference can't overflow regardless of the order.
78 checkedA = -checkedA;
79 return !checkedA.IsValid();
80}
81
Jamie Madillac43aaa2018-07-31 11:22:13 -040082bool ValidateDrawClientAttribs(Context *context)
83{
84 if (!context->getStateCache().hasAnyEnabledClientAttrib())
85 return true;
86
87 const gl::State &state = context->getGLState();
88
89 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
90 {
91 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
92 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
93 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
94 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
95 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
96 return false;
97 }
98
99 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
100 {
101 // This is an application error that would normally result in a crash, but we catch it
102 // and return an error
103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
104 return false;
105 }
106
107 return true;
108}
109
Jamie Madill5b772312018-03-08 20:28:32 -0500110bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -0400111{
Jamie Madillac43aaa2018-07-31 11:22:13 -0400112 if (!ValidateDrawClientAttribs(context))
Jamie Madill51af38b2018-04-15 08:50:56 -0400113 {
Jamie Madillac43aaa2018-07-31 11:22:13 -0400114 return false;
Jamie Madill51af38b2018-04-15 08:50:56 -0400115 }
116
117 // If we're drawing zero vertices, we have enough data.
118 if (vertexCount <= 0 || primcount <= 0)
119 {
120 return true;
121 }
122
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400123 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
124 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
Jamie Madill1ca74672015-07-21 15:14:11 -0400125 {
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400126 return true;
Jamie Madill02c9c042018-04-17 13:43:48 -0400127 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800128
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400129 // An overflow can happen when adding the offset. Negative indicates overflow.
130 if (context->getStateCache().getNonInstancedVertexElementLimit() < 0 ||
131 context->getStateCache().getInstancedVertexElementLimit() < 0)
132 {
133 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
134 return false;
135 }
136
137 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
138 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
139 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
140 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400141}
142
Jamie Madill5b772312018-03-08 20:28:32 -0500143bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400144{
145 switch (type)
146 {
147 // Types referenced in Table 3.4 of the ES 2.0.25 spec
148 case GL_UNSIGNED_BYTE:
149 case GL_UNSIGNED_SHORT_4_4_4_4:
150 case GL_UNSIGNED_SHORT_5_5_5_1:
151 case GL_UNSIGNED_SHORT_5_6_5:
152 return context->getClientVersion() >= ES_2_0;
153
154 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
155 case GL_BYTE:
156 case GL_INT:
157 case GL_SHORT:
158 case GL_UNSIGNED_INT:
159 case GL_UNSIGNED_INT_10F_11F_11F_REV:
160 case GL_UNSIGNED_INT_24_8:
161 case GL_UNSIGNED_INT_2_10_10_10_REV:
162 case GL_UNSIGNED_INT_5_9_9_9_REV:
163 case GL_UNSIGNED_SHORT:
164 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
165 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
166 return context->getClientVersion() >= ES_3_0;
167
168 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400169 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
170 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400171
172 case GL_HALF_FLOAT:
173 return context->getClientVersion() >= ES_3_0 ||
174 context->getExtensions().textureHalfFloat;
175
176 case GL_HALF_FLOAT_OES:
177 return context->getExtensions().colorBufferHalfFloat;
178
179 default:
180 return false;
181 }
182}
183
Jamie Madill5b772312018-03-08 20:28:32 -0500184bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400185{
186 switch (format)
187 {
188 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
189 case GL_RGBA:
190 case GL_RGB:
191 case GL_ALPHA:
192 return context->getClientVersion() >= ES_2_0;
193
194 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
195 case GL_RG:
196 case GL_RED:
197 case GL_RGBA_INTEGER:
198 case GL_RGB_INTEGER:
199 case GL_RG_INTEGER:
200 case GL_RED_INTEGER:
201 return context->getClientVersion() >= ES_3_0;
202
203 case GL_SRGB_ALPHA_EXT:
204 case GL_SRGB_EXT:
205 return context->getExtensions().sRGB;
206
207 case GL_BGRA_EXT:
208 return context->getExtensions().readFormatBGRA;
209
210 default:
211 return false;
212 }
213}
214
Jamie Madill5b772312018-03-08 20:28:32 -0500215bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400216 GLenum framebufferComponentType,
217 GLenum format,
218 GLenum type)
219{
220 switch (framebufferComponentType)
221 {
222 case GL_UNSIGNED_NORMALIZED:
223 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
224 // ReadPixels with BGRA even if the extension is not present
225 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
226 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
227 type == GL_UNSIGNED_BYTE);
228
229 case GL_SIGNED_NORMALIZED:
230 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
231
232 case GL_INT:
233 return (format == GL_RGBA_INTEGER && type == GL_INT);
234
235 case GL_UNSIGNED_INT:
236 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
237
238 case GL_FLOAT:
239 return (format == GL_RGBA && type == GL_FLOAT);
240
241 default:
242 UNREACHABLE();
243 return false;
244 }
245}
246
Geoff Langc1984ed2016-10-07 12:41:00 -0400247template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400248bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400249{
250 switch (ConvertToGLenum(params[0]))
251 {
252 case GL_CLAMP_TO_EDGE:
253 break;
254
255 case GL_REPEAT:
256 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400257 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400258 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400259 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700260 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400261 return false;
262 }
263 break;
264
265 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700266 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400267 return false;
268 }
269
270 return true;
271}
272
273template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400274bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400275{
276 switch (ConvertToGLenum(params[0]))
277 {
278 case GL_NEAREST:
279 case GL_LINEAR:
280 break;
281
282 case GL_NEAREST_MIPMAP_NEAREST:
283 case GL_LINEAR_MIPMAP_NEAREST:
284 case GL_NEAREST_MIPMAP_LINEAR:
285 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400286 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400287 {
288 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700289 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400290 return false;
291 }
292 break;
293
294 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700295 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400296 return false;
297 }
298
299 return true;
300}
301
302template <typename ParamType>
303bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
304{
305 switch (ConvertToGLenum(params[0]))
306 {
307 case GL_NEAREST:
308 case GL_LINEAR:
309 break;
310
311 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700312 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400313 return false;
314 }
315
316 return true;
317}
318
319template <typename ParamType>
320bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
321{
322 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
323 switch (ConvertToGLenum(params[0]))
324 {
325 case GL_NONE:
326 case GL_COMPARE_REF_TO_TEXTURE:
327 break;
328
329 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700330 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400331 return false;
332 }
333
334 return true;
335}
336
337template <typename ParamType>
338bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
339{
340 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
341 switch (ConvertToGLenum(params[0]))
342 {
343 case GL_LEQUAL:
344 case GL_GEQUAL:
345 case GL_LESS:
346 case GL_GREATER:
347 case GL_EQUAL:
348 case GL_NOTEQUAL:
349 case GL_ALWAYS:
350 case GL_NEVER:
351 break;
352
353 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400355 return false;
356 }
357
358 return true;
359}
360
361template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700362bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
363{
364 if (!context->getExtensions().textureSRGBDecode)
365 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700366 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700367 return false;
368 }
369
370 switch (ConvertToGLenum(params[0]))
371 {
372 case GL_DECODE_EXT:
373 case GL_SKIP_DECODE_EXT:
374 break;
375
376 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700378 return false;
379 }
380
381 return true;
382}
383
Luc Ferron1b1a8642018-01-23 15:12:01 -0500384bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
385{
386 if (!context->getExtensions().textureFilterAnisotropic)
387 {
388 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
389 return false;
390 }
391
392 return true;
393}
394
395bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
396{
397 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
398 {
399 return false;
400 }
401
402 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
403
404 if (paramValue < 1 || paramValue > largest)
405 {
406 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
407 return false;
408 }
409
410 return true;
411}
412
Jamie Madill5b772312018-03-08 20:28:32 -0500413bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400414{
415 const Program *program = context->getGLState().getProgram();
416 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
417
Brandon Jonesc405ae72017-12-06 14:15:03 -0800418 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
419 framebuffer->getDrawBufferTypeMask().to_ulong(),
420 program->getActiveOutputVariables().to_ulong(),
421 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400422 {
Brandon Jones76746f92017-11-22 11:44:41 -0800423 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
424 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400425 }
426
427 return true;
428}
429
Jamie Madill5b772312018-03-08 20:28:32 -0500430bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400431{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700432 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400433 const Program *program = context->getGLState().getProgram();
434 const VertexArray *vao = context->getGLState().getVertexArray();
435
Brandon Jonesc405ae72017-12-06 14:15:03 -0800436 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
437 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
438 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
439
440 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
441 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
442 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
443
444 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
445 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400446 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800447 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
448 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400449 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400450 return true;
451}
452
Jamie Madill493f9572018-05-24 19:52:15 -0400453bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
454 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800455{
456 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400457 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800458 {
Jamie Madill493f9572018-05-24 19:52:15 -0400459 case PrimitiveMode::Points:
460 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
461 case PrimitiveMode::Lines:
462 case PrimitiveMode::LineStrip:
463 case PrimitiveMode::LineLoop:
464 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
465 case PrimitiveMode::LinesAdjacency:
466 case PrimitiveMode::LineStripAdjacency:
467 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
468 case PrimitiveMode::Triangles:
469 case PrimitiveMode::TriangleFan:
470 case PrimitiveMode::TriangleStrip:
471 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
472 case PrimitiveMode::TrianglesAdjacency:
473 case PrimitiveMode::TriangleStripAdjacency:
474 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800475 default:
476 UNREACHABLE();
477 return false;
478 }
479}
480
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700481// GLES1 texture parameters are a small subset of the others
482bool IsValidGLES1TextureParameter(GLenum pname)
483{
484 switch (pname)
485 {
486 case GL_TEXTURE_MAG_FILTER:
487 case GL_TEXTURE_MIN_FILTER:
488 case GL_TEXTURE_WRAP_S:
489 case GL_TEXTURE_WRAP_T:
490 case GL_TEXTURE_WRAP_R:
491 case GL_GENERATE_MIPMAP:
492 case GL_TEXTURE_CROP_RECT_OES:
493 return true;
494 default:
495 return false;
496 }
497}
498
Geoff Langf41a7152016-09-19 15:11:17 -0400499} // anonymous namespace
500
Brandon Jonesd1049182018-03-28 10:02:20 -0700501void SetRobustLengthParam(GLsizei *length, GLsizei value)
502{
503 if (length)
504 {
505 *length = value;
506 }
507}
508
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500509bool IsETC2EACFormat(const GLenum format)
510{
511 // ES 3.1, Table 8.19
512 switch (format)
513 {
514 case GL_COMPRESSED_R11_EAC:
515 case GL_COMPRESSED_SIGNED_R11_EAC:
516 case GL_COMPRESSED_RG11_EAC:
517 case GL_COMPRESSED_SIGNED_RG11_EAC:
518 case GL_COMPRESSED_RGB8_ETC2:
519 case GL_COMPRESSED_SRGB8_ETC2:
520 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
521 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
522 case GL_COMPRESSED_RGBA8_ETC2_EAC:
523 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
524 return true;
525
526 default:
527 return false;
528 }
529}
530
Jamie Madill5b772312018-03-08 20:28:32 -0500531bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400532{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800533 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400534 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800535 case TextureType::_2D:
536 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800537 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400538
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800539 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400540 return context->getExtensions().textureRectangle;
541
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800542 case TextureType::_3D:
543 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800544 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500545
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800546 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800547 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400548
He Yunchaoced53ae2016-11-29 15:00:51 +0800549 default:
550 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500551 }
Jamie Madill35d15012013-10-07 10:46:37 -0400552}
553
Jamie Madill5b772312018-03-08 20:28:32 -0500554bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500555{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800556 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500557 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800558 case TextureType::_2D:
559 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500560 return true;
561
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800562 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400563 return context->getExtensions().textureRectangle;
564
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500565 default:
566 return false;
567 }
568}
569
Jamie Madill5b772312018-03-08 20:28:32 -0500570bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500571{
572 switch (target)
573 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800574 case TextureType::_3D:
575 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300576 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500577
578 default:
579 return false;
580 }
581}
582
Ian Ewellbda75592016-04-18 17:25:54 -0400583// Most texture GL calls are not compatible with external textures, so we have a separate validation
584// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500585bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400586{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800587 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400588 (context->getExtensions().eglImageExternal ||
589 context->getExtensions().eglStreamConsumerExternal);
590}
591
Shannon Woods4dfed832014-03-17 20:03:39 -0400592// This function differs from ValidTextureTarget in that the target must be
593// usable as the destination of a 2D operation-- so a cube face is valid, but
594// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400595// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500596bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400597{
598 switch (target)
599 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800600 case TextureTarget::_2D:
601 case TextureTarget::CubeMapNegativeX:
602 case TextureTarget::CubeMapNegativeY:
603 case TextureTarget::CubeMapNegativeZ:
604 case TextureTarget::CubeMapPositiveX:
605 case TextureTarget::CubeMapPositiveY:
606 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800607 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800608 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400609 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800610 default:
611 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500612 }
613}
614
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800615bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400616 PrimitiveMode transformFeedbackPrimitiveMode,
617 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800618{
619 ASSERT(context);
620
621 if (!context->getExtensions().geometryShader)
622 {
623 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
624 // that does not match the current transform feedback object's draw mode (if transform
625 // feedback is active), (3.0.2, section 2.14, pg 86)
626 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
627 }
628
629 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400630 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800631 {
Jamie Madill493f9572018-05-24 19:52:15 -0400632 case PrimitiveMode::Points:
633 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
634 case PrimitiveMode::Lines:
635 case PrimitiveMode::LineStrip:
636 case PrimitiveMode::LineLoop:
637 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
638 case PrimitiveMode::Triangles:
639 case PrimitiveMode::TriangleFan:
640 case PrimitiveMode::TriangleStrip:
641 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800642 default:
643 UNREACHABLE();
644 return false;
645 }
646}
647
Jamie Madill5b772312018-03-08 20:28:32 -0500648bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400649 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400650 GLsizei count,
651 GLenum type,
652 const GLvoid *indices,
653 GLsizei primcount)
654{
655 if (primcount < 0)
656 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700657 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400658 return false;
659 }
660
661 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
662 {
663 return false;
664 }
665
Jamie Madill9fdaa492018-02-16 10:52:11 -0500666 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400667}
668
669bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400670 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400671 GLint first,
672 GLsizei count,
673 GLsizei primcount)
674{
675 if (primcount < 0)
676 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700677 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400678 return false;
679 }
680
681 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
682 {
683 return false;
684 }
685
Jamie Madill9fdaa492018-02-16 10:52:11 -0500686 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400687}
688
Jamie Madill5b772312018-03-08 20:28:32 -0500689bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400690{
691 // Verify there is at least one active attribute with a divisor of zero
692 const State &state = context->getGLState();
693
694 Program *program = state.getProgram();
695
696 const auto &attribs = state.getVertexArray()->getVertexAttributes();
697 const auto &bindings = state.getVertexArray()->getVertexBindings();
698 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
699 {
700 const VertexAttribute &attrib = attribs[attributeIndex];
701 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300702 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400703 {
704 return true;
705 }
706 }
707
Brandon Jonesafa75152017-07-21 13:11:29 -0700708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400709 return false;
710}
711
Jamie Madill5b772312018-03-08 20:28:32 -0500712bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500713{
714 switch (target)
715 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800716 case TextureType::_3D:
717 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800718 return true;
719 default:
720 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400721 }
722}
723
Jamie Madill5b772312018-03-08 20:28:32 -0500724bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800725{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800726 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800727 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800728 case TextureType::_2D:
729 case TextureType::_2DArray:
730 case TextureType::_2DMultisample:
731 case TextureType::CubeMap:
732 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800733 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800734 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400735 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800736 default:
737 return false;
738 }
739}
740
Jamie Madill5b772312018-03-08 20:28:32 -0500741bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500742{
He Yunchaoced53ae2016-11-29 15:00:51 +0800743 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
744 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400745 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500746
747 switch (target)
748 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800749 case GL_FRAMEBUFFER:
750 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400751
He Yunchaoced53ae2016-11-29 15:00:51 +0800752 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800753 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400754 return (context->getExtensions().framebufferBlit ||
755 context->getClientMajorVersion() >= 3);
756
He Yunchaoced53ae2016-11-29 15:00:51 +0800757 default:
758 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500759 }
760}
761
Jamie Madill5b772312018-03-08 20:28:32 -0500762bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400763{
Jamie Madillc29968b2016-01-20 11:17:23 -0500764 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400765 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800766 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400767 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800768 case TextureType::_2D:
769 case TextureType::_2DArray:
770 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500771 maxDimension = caps.max2DTextureSize;
772 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800773 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800774 maxDimension = caps.maxCubeMapTextureSize;
775 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800776 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400777 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800778 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800779 maxDimension = caps.max3DTextureSize;
780 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800781 default:
782 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400783 }
784
Brandon Jones6cad5662017-06-14 13:25:13 -0700785 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400786}
787
Jamie Madill5b772312018-03-08 20:28:32 -0500788bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800789 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700790 GLint level,
791 GLsizei width,
792 GLsizei height,
793 GLsizei depth,
794 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400795{
Brandon Jones6cad5662017-06-14 13:25:13 -0700796 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400797 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700798 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400799 return false;
800 }
Austin Kinross08528e12015-10-07 16:24:40 -0700801 // TexSubImage parameters can be NPOT without textureNPOT extension,
802 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500803 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500804 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500805 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400806 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400807 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700808 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400809 return false;
810 }
811
812 if (!ValidMipLevel(context, target, level))
813 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700814 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400815 return false;
816 }
817
818 return true;
819}
820
Geoff Lang966c9402017-04-18 12:38:27 -0400821bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
822{
823 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
824 (size % blockSize == 0);
825}
826
Jamie Madill5b772312018-03-08 20:28:32 -0500827bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500828 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400829 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500830 GLsizei width,
831 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400832{
Geoff Langca271392017-04-05 12:30:00 -0400833 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400834 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400835 {
836 return false;
837 }
838
Geoff Lang966c9402017-04-18 12:38:27 -0400839 if (width < 0 || height < 0)
840 {
841 return false;
842 }
843
844 if (CompressedTextureFormatRequiresExactSize(internalFormat))
845 {
846 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
847 // block size for level 0 but WebGL disallows this.
848 bool smallerThanBlockSizeAllowed =
849 level > 0 || !context->getExtensions().webglCompatibility;
850
851 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
852 smallerThanBlockSizeAllowed) ||
853 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
854 smallerThanBlockSizeAllowed))
855 {
856 return false;
857 }
858 }
859
860 return true;
861}
862
Jamie Madill5b772312018-03-08 20:28:32 -0500863bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400864 GLenum internalFormat,
865 GLint xoffset,
866 GLint yoffset,
867 GLsizei width,
868 GLsizei height,
869 size_t textureWidth,
870 size_t textureHeight)
871{
872 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
873 if (!formatInfo.compressed)
874 {
875 return false;
876 }
877
Geoff Lang44ff5a72017-02-03 15:15:43 -0500878 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400879 {
880 return false;
881 }
882
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500883 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400884 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500885 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400886 yoffset % formatInfo.compressedBlockHeight != 0)
887 {
888 return false;
889 }
890
891 // Allowed to either have data that is a multiple of block size or is smaller than the block
892 // size but fills the entire mip
893 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
894 static_cast<size_t>(width) == textureWidth &&
895 static_cast<size_t>(height) == textureHeight;
896 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
897 (height % formatInfo.compressedBlockHeight) == 0;
898 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400899 {
900 return false;
901 }
902 }
903
Geoff Langd4f180b2013-09-24 13:57:44 -0400904 return true;
905}
906
Jamie Madill5b772312018-03-08 20:28:32 -0500907bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800908 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400909 GLsizei width,
910 GLsizei height,
911 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400912 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400913 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400914 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400915 GLsizei imageSize)
916{
Corentin Wallez336129f2017-10-17 15:55:40 -0400917 gl::Buffer *pixelUnpackBuffer =
918 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400919 if (pixelUnpackBuffer == nullptr && imageSize < 0)
920 {
921 // Checks are not required
922 return true;
923 }
924
925 // ...the data would be unpacked from the buffer object such that the memory reads required
926 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400927 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
928 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400929 const gl::Extents size(width, height, depth);
930 const auto &unpack = context->getGLState().getUnpackState();
931
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800932 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400933 GLuint endByte = 0;
934 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400935 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400936 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400937 return false;
938 }
939
Geoff Langff5b2d52016-09-07 11:32:23 -0400940 if (pixelUnpackBuffer)
941 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400942 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400943 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
944 checkedEndByte += checkedOffset;
945
946 if (!checkedEndByte.IsValid() ||
947 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
948 {
949 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400950 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400951 return false;
952 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800953 if (context->getExtensions().webglCompatibility &&
954 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
955 {
956 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
957 PixelUnpackBufferBoundForTransformFeedback);
958 return false;
959 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400960 }
961 else
962 {
963 ASSERT(imageSize >= 0);
964 if (pixels == nullptr && imageSize != 0)
965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500966 context->handleError(InvalidOperation()
967 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400968 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400969 }
970
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400971 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500973 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400974 return false;
975 }
976 }
977
978 return true;
979}
980
Corentin Wallezad3ae902018-03-09 13:40:42 -0500981bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500982{
Geoff Lang37dde692014-01-31 16:34:54 -0500983 switch (queryType)
984 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500985 case QueryType::AnySamples:
986 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400987 return context->getClientMajorVersion() >= 3 ||
988 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500989 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800990 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500991 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800992 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500993 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800994 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500995 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800996 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800997 default:
998 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500999 }
1000}
1001
Jamie Madill5b772312018-03-08 20:28:32 -05001002bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001003 GLenum type,
1004 GLboolean normalized,
1005 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001006 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001007 bool pureInteger)
1008{
1009 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001010 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1011 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1012 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1013 // parameter exceeds 255.
1014 constexpr GLsizei kMaxWebGLStride = 255;
1015 if (stride > kMaxWebGLStride)
1016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001017 context->handleError(InvalidValue()
1018 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001019 return false;
1020 }
1021
1022 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1023 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1024 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1025 // or an INVALID_OPERATION error is generated.
1026 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1027 size_t typeSize = GetVertexFormatTypeSize(internalType);
1028
1029 ASSERT(isPow2(typeSize) && typeSize > 0);
1030 size_t sizeMask = (typeSize - 1);
1031 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1032 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001033 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001034 return false;
1035 }
1036
1037 if ((stride & sizeMask) != 0)
1038 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001039 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001040 return false;
1041 }
1042
1043 return true;
1044}
1045
Jamie Madill5b772312018-03-08 20:28:32 -05001046Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001047{
He Yunchaoced53ae2016-11-29 15:00:51 +08001048 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1049 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1050 // or program object and INVALID_OPERATION if the provided name identifies an object
1051 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001052
Dian Xiang769769a2015-09-09 15:20:08 -07001053 Program *validProgram = context->getProgram(id);
1054
1055 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001056 {
Dian Xiang769769a2015-09-09 15:20:08 -07001057 if (context->getShader(id))
1058 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001060 }
1061 else
1062 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001063 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001064 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001065 }
Dian Xiang769769a2015-09-09 15:20:08 -07001066
1067 return validProgram;
1068}
1069
Jamie Madill5b772312018-03-08 20:28:32 -05001070Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001071{
1072 // See ValidProgram for spec details.
1073
1074 Shader *validShader = context->getShader(id);
1075
1076 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001077 {
Dian Xiang769769a2015-09-09 15:20:08 -07001078 if (context->getProgram(id))
1079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001081 }
1082 else
1083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001084 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001085 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001086 }
Dian Xiang769769a2015-09-09 15:20:08 -07001087
1088 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001089}
1090
Geoff Langb1196682014-07-23 13:47:29 -04001091bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001092{
Geoff Langfa125c92017-10-24 13:01:46 -04001093 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001094 {
Geoff Langfa125c92017-10-24 13:01:46 -04001095 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1096 {
1097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1098 return false;
1099 }
Jamie Madillb4472272014-07-03 10:38:55 -04001100
Geoff Langfa125c92017-10-24 13:01:46 -04001101 // Color attachment 0 is validated below because it is always valid
1102 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001103 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001104 {
Geoff Langfa125c92017-10-24 13:01:46 -04001105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001107 }
1108 }
1109 else
1110 {
1111 switch (attachment)
1112 {
Geoff Langfa125c92017-10-24 13:01:46 -04001113 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 case GL_DEPTH_ATTACHMENT:
1115 case GL_STENCIL_ATTACHMENT:
1116 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001117
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 case GL_DEPTH_STENCIL_ATTACHMENT:
1119 if (!context->getExtensions().webglCompatibility &&
1120 context->getClientMajorVersion() < 3)
1121 {
Geoff Langfa125c92017-10-24 13:01:46 -04001122 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001123 return false;
1124 }
1125 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001126
He Yunchaoced53ae2016-11-29 15:00:51 +08001127 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001129 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001130 }
1131 }
1132
1133 return true;
1134}
1135
Jamie Madill5b772312018-03-08 20:28:32 -05001136bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001137 GLenum target,
1138 GLsizei samples,
1139 GLenum internalformat,
1140 GLsizei width,
1141 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001142{
1143 switch (target)
1144 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001145 case GL_RENDERBUFFER:
1146 break;
1147 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001149 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001150 }
1151
1152 if (width < 0 || height < 0 || samples < 0)
1153 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001154 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001155 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001156 }
1157
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001158 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1159 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1160
1161 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001162 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001164 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001165 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001166 }
1167
1168 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1169 // 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 -08001170 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001171 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1172 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001175 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 }
1177
Geoff Langaae65a42014-05-26 12:43:44 -04001178 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001180 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 }
1183
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001184 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001185 if (handle == 0)
1186 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001187 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001189 }
1190
1191 return true;
1192}
1193
He Yunchaoced53ae2016-11-29 15:00:51 +08001194bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1195 GLenum target,
1196 GLenum attachment,
1197 GLenum renderbuffertarget,
1198 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001199{
Geoff Lange8afa902017-09-27 15:00:43 -04001200 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001202 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001203 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001204 }
1205
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001206 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207
Jamie Madill84115c92015-04-23 15:00:07 -04001208 ASSERT(framebuffer);
1209 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001210 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001211 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001212 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001213 }
1214
Jamie Madillb4472272014-07-03 10:38:55 -04001215 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001216 {
Jamie Madillb4472272014-07-03 10:38:55 -04001217 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001218 }
1219
Jamie Madillab9d82c2014-01-21 16:38:14 -05001220 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1221 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1222 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1223 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1224 if (renderbuffer != 0)
1225 {
1226 if (!context->getRenderbuffer(renderbuffer))
1227 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001229 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001230 }
1231 }
1232
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001233 return true;
1234}
1235
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001236bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001237 GLint srcX0,
1238 GLint srcY0,
1239 GLint srcX1,
1240 GLint srcY1,
1241 GLint dstX0,
1242 GLint dstY0,
1243 GLint dstX1,
1244 GLint dstY1,
1245 GLbitfield mask,
1246 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247{
1248 switch (filter)
1249 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001250 case GL_NEAREST:
1251 break;
1252 case GL_LINEAR:
1253 break;
1254 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001255 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 }
1258
1259 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001261 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001262 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001263 }
1264
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001265 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1266 // color buffer, leaving only nearest being unfiltered from above
1267 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001269 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001270 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271 }
1272
Jamie Madill51f40ec2016-06-15 14:06:00 -04001273 const auto &glState = context->getGLState();
1274 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1275 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001276
1277 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001279 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001280 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001281 }
1282
Jamie Madill427064d2018-04-13 16:20:34 -04001283 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001284 {
Jamie Madill48faf802014-11-06 15:27:22 -05001285 return false;
1286 }
1287
Jamie Madill427064d2018-04-13 16:20:34 -04001288 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001289 {
Jamie Madill48faf802014-11-06 15:27:22 -05001290 return false;
1291 }
1292
Qin Jiajiaaef92162018-02-27 13:51:44 +08001293 if (readFramebuffer->id() == drawFramebuffer->id())
1294 {
1295 context->handleError(InvalidOperation());
1296 return false;
1297 }
1298
Jamie Madille98b1b52018-03-08 09:47:23 -05001299 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001300 {
Geoff Langb1196682014-07-23 13:47:29 -04001301 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001302 }
1303
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001304 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1305 // always run it in order to avoid triggering driver bugs.
1306 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1307 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001308 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001309 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1310 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001311 }
1312
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001313 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1314
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001315 if (mask & GL_COLOR_BUFFER_BIT)
1316 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001317 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001318 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001319
He Yunchao66a41a22016-12-15 16:45:05 +08001320 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001321 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001322 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323
Geoff Langa15472a2015-08-11 11:48:03 -04001324 for (size_t drawbufferIdx = 0;
1325 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001326 {
Geoff Langa15472a2015-08-11 11:48:03 -04001327 const FramebufferAttachment *attachment =
1328 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1329 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001331 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332
Geoff Langb2f3d052013-08-13 12:49:27 -04001333 // The GL ES 3.0.2 spec (pg 193) states that:
1334 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001335 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1336 // as well
1337 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1338 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001339 // Changes with EXT_color_buffer_float:
1340 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001341 GLenum readComponentType = readFormat.info->componentType;
1342 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001343 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001344 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001345 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001346 drawComponentType == GL_SIGNED_NORMALIZED);
1347
1348 if (extensions.colorBufferFloat)
1349 {
1350 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1351 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1352
1353 if (readFixedOrFloat != drawFixedOrFloat)
1354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001355 context->handleError(InvalidOperation()
1356 << "If the read buffer contains fixed-point or "
1357 "floating-point values, the draw buffer must "
1358 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001359 return false;
1360 }
1361 }
1362 else if (readFixedPoint != drawFixedPoint)
1363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 context->handleError(InvalidOperation()
1365 << "If the read buffer contains fixed-point values, "
1366 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001367 return false;
1368 }
1369
1370 if (readComponentType == GL_UNSIGNED_INT &&
1371 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001373 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001374 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 }
1376
Jamie Madill6163c752015-12-07 16:32:59 -05001377 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001379 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001380 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 }
1382
Jamie Madilla3944d42016-07-22 22:13:26 -04001383 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001384 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001386 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001387 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 }
Geoff Lange4915782017-04-12 15:19:07 -04001389
1390 if (context->getExtensions().webglCompatibility &&
1391 *readColorBuffer == *attachment)
1392 {
1393 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001394 InvalidOperation()
1395 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001396 return false;
1397 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 }
1399 }
1400
Jamie Madilla3944d42016-07-22 22:13:26 -04001401 if ((readFormat.info->componentType == GL_INT ||
1402 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1403 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001406 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 }
He Yunchao66a41a22016-12-15 16:45:05 +08001409 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1410 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1411 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1412 // situation is an application error that would lead to a crash in ANGLE.
1413 else if (drawFramebuffer->hasEnabledDrawBuffer())
1414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001415 context->handleError(
1416 InvalidOperation()
1417 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001418 return false;
1419 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001420 }
1421
He Yunchaoced53ae2016-11-29 15:00:51 +08001422 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001423 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1424 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001426 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001428 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001429 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001430 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001431 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001433 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001434 {
Kenneth Russell69382852017-07-21 16:38:44 -04001435 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001437 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001438 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001439 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001440
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001441 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001443 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001444 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 }
Geoff Lange4915782017-04-12 15:19:07 -04001446
1447 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001449 context->handleError(
1450 InvalidOperation()
1451 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001452 return false;
1453 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
He Yunchao66a41a22016-12-15 16:45:05 +08001455 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1456 else if (drawBuffer)
1457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001458 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1459 "depth/stencil attachment of a "
1460 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001461 return false;
1462 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001463 }
1464 }
1465
Martin Radeva3ed4572017-07-27 18:29:37 +03001466 // ANGLE_multiview, Revision 1:
1467 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001468 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1469 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1470 // views in the current read framebuffer is more than one.
1471 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001472 {
1473 context->handleError(InvalidFramebufferOperation()
1474 << "Attempt to read from a multi-view framebuffer.");
1475 return false;
1476 }
1477 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1478 {
1479 context->handleError(InvalidFramebufferOperation()
1480 << "Attempt to write to a multi-view framebuffer.");
1481 return false;
1482 }
1483
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001484 return true;
1485}
1486
Jamie Madill4928b7c2017-06-20 12:57:39 -04001487bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001488 GLint x,
1489 GLint y,
1490 GLsizei width,
1491 GLsizei height,
1492 GLenum format,
1493 GLenum type,
1494 GLsizei bufSize,
1495 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001496 GLsizei *columns,
1497 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001498 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001499{
1500 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001501 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001502 return false;
1503 }
1504
Brandon Jonesd1049182018-03-28 10:02:20 -07001505 GLsizei writeLength = 0;
1506 GLsizei writeColumns = 0;
1507 GLsizei writeRows = 0;
1508
1509 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1510 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001511 {
Geoff Langb1196682014-07-23 13:47:29 -04001512 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001513 }
1514
Brandon Jonesd1049182018-03-28 10:02:20 -07001515 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001516 {
Geoff Langb1196682014-07-23 13:47:29 -04001517 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001518 }
1519
Brandon Jonesd1049182018-03-28 10:02:20 -07001520 SetRobustLengthParam(length, writeLength);
1521 SetRobustLengthParam(columns, writeColumns);
1522 SetRobustLengthParam(rows, writeRows);
1523
Jamie Madillc29968b2016-01-20 11:17:23 -05001524 return true;
1525}
1526
1527bool ValidateReadnPixelsEXT(Context *context,
1528 GLint x,
1529 GLint y,
1530 GLsizei width,
1531 GLsizei height,
1532 GLenum format,
1533 GLenum type,
1534 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001535 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001536{
1537 if (bufSize < 0)
1538 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001539 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001540 return false;
1541 }
1542
Geoff Lang62fce5b2016-09-30 10:46:35 -04001543 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001544 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001545}
Jamie Madill26e91952014-03-05 15:01:27 -05001546
Jamie Madill4928b7c2017-06-20 12:57:39 -04001547bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001548 GLint x,
1549 GLint y,
1550 GLsizei width,
1551 GLsizei height,
1552 GLenum format,
1553 GLenum type,
1554 GLsizei bufSize,
1555 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001556 GLsizei *columns,
1557 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001558 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001559{
Brandon Jonesd1049182018-03-28 10:02:20 -07001560 GLsizei writeLength = 0;
1561 GLsizei writeColumns = 0;
1562 GLsizei writeRows = 0;
1563
Geoff Lang62fce5b2016-09-30 10:46:35 -04001564 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001565 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001566 return false;
1567 }
1568
Brandon Jonesd1049182018-03-28 10:02:20 -07001569 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1570 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001571 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001572 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001573 }
1574
Brandon Jonesd1049182018-03-28 10:02:20 -07001575 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001576 {
1577 return false;
1578 }
1579
Brandon Jonesd1049182018-03-28 10:02:20 -07001580 SetRobustLengthParam(length, writeLength);
1581 SetRobustLengthParam(columns, writeColumns);
1582 SetRobustLengthParam(rows, writeRows);
1583
Geoff Lang62fce5b2016-09-30 10:46:35 -04001584 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001585}
1586
Jamie Madillf0e04492017-08-26 15:28:42 -04001587bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001588{
1589 if (!context->getExtensions().occlusionQueryBoolean &&
1590 !context->getExtensions().disjointTimerQuery)
1591 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001592 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001593 return false;
1594 }
1595
Olli Etuaho41997e72016-03-10 13:38:39 +02001596 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001597}
1598
Jamie Madillf0e04492017-08-26 15:28:42 -04001599bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001600{
1601 if (!context->getExtensions().occlusionQueryBoolean &&
1602 !context->getExtensions().disjointTimerQuery)
1603 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001604 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001605 return false;
1606 }
1607
Olli Etuaho41997e72016-03-10 13:38:39 +02001608 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001609}
1610
Jamie Madillf0e04492017-08-26 15:28:42 -04001611bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1612{
1613 if (!context->getExtensions().occlusionQueryBoolean &&
1614 !context->getExtensions().disjointTimerQuery)
1615 {
1616 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1617 return false;
1618 }
1619
1620 return true;
1621}
1622
Corentin Wallezad3ae902018-03-09 13:40:42 -05001623bool ValidateBeginQueryBase(gl::Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001624{
1625 if (!ValidQueryType(context, target))
1626 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001627 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001628 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001629 }
1630
1631 if (id == 0)
1632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001633 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001634 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001635 }
1636
1637 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1638 // of zero, if the active query object name for <target> is non-zero (for the
1639 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1640 // the active query for either target is non-zero), if <id> is the name of an
1641 // existing query object whose type does not match <target>, or if <id> is the
1642 // active query object name for any query type, the error INVALID_OPERATION is
1643 // generated.
1644
1645 // Ensure no other queries are active
1646 // NOTE: If other queries than occlusion are supported, we will need to check
1647 // separately that:
1648 // a) The query ID passed is not the current active query for any target/type
1649 // b) There are no active queries for the requested target (and in the case
1650 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1651 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001652
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001653 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001655 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001656 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001657 }
1658
1659 Query *queryObject = context->getQuery(id, true, target);
1660
1661 // check that name was obtained with glGenQueries
1662 if (!queryObject)
1663 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001664 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001665 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001666 }
1667
1668 // check for type mismatch
1669 if (queryObject->getType() != target)
1670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001671 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001672 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001673 }
1674
1675 return true;
1676}
1677
Corentin Wallezad3ae902018-03-09 13:40:42 -05001678bool ValidateBeginQueryEXT(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001679{
1680 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001681 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001682 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001683 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684 return false;
1685 }
1686
1687 return ValidateBeginQueryBase(context, target, id);
1688}
1689
Corentin Wallezad3ae902018-03-09 13:40:42 -05001690bool ValidateEndQueryBase(gl::Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001691{
1692 if (!ValidQueryType(context, target))
1693 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001694 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001695 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001696 }
1697
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001698 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001699
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001702 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001703 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001704 }
1705
Jamie Madill45c785d2014-05-13 14:09:34 -04001706 return true;
1707}
1708
Corentin Wallezad3ae902018-03-09 13:40:42 -05001709bool ValidateEndQueryEXT(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001710{
1711 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001712 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001714 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715 return false;
1716 }
1717
1718 return ValidateEndQueryBase(context, target);
1719}
1720
Corentin Wallezad3ae902018-03-09 13:40:42 -05001721bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722{
1723 if (!context->getExtensions().disjointTimerQuery)
1724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001725 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001726 return false;
1727 }
1728
Corentin Wallezad3ae902018-03-09 13:40:42 -05001729 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001730 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001731 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 return false;
1733 }
1734
1735 Query *queryObject = context->getQuery(id, true, target);
1736 if (queryObject == nullptr)
1737 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001738 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001739 return false;
1740 }
1741
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001742 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001743 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001744 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001745 return false;
1746 }
1747
1748 return true;
1749}
1750
Corentin Wallezad3ae902018-03-09 13:40:42 -05001751bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752{
Geoff Lang2186c382016-10-14 10:54:54 -04001753 if (numParams)
1754 {
1755 *numParams = 0;
1756 }
1757
Corentin Wallezad3ae902018-03-09 13:40:42 -05001758 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001760 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001761 return false;
1762 }
1763
1764 switch (pname)
1765 {
1766 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001767 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001768 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001769 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770 return false;
1771 }
1772 break;
1773 case GL_QUERY_COUNTER_BITS_EXT:
1774 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001775 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001776 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001777 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001778 return false;
1779 }
1780 break;
1781 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001782 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001783 return false;
1784 }
1785
Geoff Lang2186c382016-10-14 10:54:54 -04001786 if (numParams)
1787 {
1788 // All queries return only one value
1789 *numParams = 1;
1790 }
1791
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001792 return true;
1793}
1794
Corentin Wallezad3ae902018-03-09 13:40:42 -05001795bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001796{
1797 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001798 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001799 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001800 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001801 return false;
1802 }
1803
Geoff Lang2186c382016-10-14 10:54:54 -04001804 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001805}
1806
Geoff Lang2186c382016-10-14 10:54:54 -04001807bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001808 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001809 GLenum pname,
1810 GLsizei bufSize,
1811 GLsizei *length,
1812 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001813{
Geoff Lang2186c382016-10-14 10:54:54 -04001814 if (!ValidateRobustEntryPoint(context, bufSize))
1815 {
1816 return false;
1817 }
1818
Brandon Jonesd1049182018-03-28 10:02:20 -07001819 GLsizei numParams = 0;
1820
1821 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001822 {
1823 return false;
1824 }
1825
Brandon Jonesd1049182018-03-28 10:02:20 -07001826 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001827 {
1828 return false;
1829 }
1830
Brandon Jonesd1049182018-03-28 10:02:20 -07001831 SetRobustLengthParam(length, numParams);
1832
Geoff Lang2186c382016-10-14 10:54:54 -04001833 return true;
1834}
1835
1836bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1837{
1838 if (numParams)
1839 {
1840 *numParams = 0;
1841 }
1842
Corentin Wallezad3ae902018-03-09 13:40:42 -05001843 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001844
1845 if (!queryObject)
1846 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001848 return false;
1849 }
1850
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001851 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001852 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001853 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001854 return false;
1855 }
1856
1857 switch (pname)
1858 {
1859 case GL_QUERY_RESULT_EXT:
1860 case GL_QUERY_RESULT_AVAILABLE_EXT:
1861 break;
1862
1863 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001864 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865 return false;
1866 }
1867
Geoff Lang2186c382016-10-14 10:54:54 -04001868 if (numParams)
1869 {
1870 *numParams = 1;
1871 }
1872
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873 return true;
1874}
1875
1876bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1877{
1878 if (!context->getExtensions().disjointTimerQuery)
1879 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001880 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001881 return false;
1882 }
Geoff Lang2186c382016-10-14 10:54:54 -04001883 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1884}
1885
1886bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1887 GLuint id,
1888 GLenum pname,
1889 GLsizei bufSize,
1890 GLsizei *length,
1891 GLint *params)
1892{
1893 if (!context->getExtensions().disjointTimerQuery)
1894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001895 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001896 return false;
1897 }
1898
1899 if (!ValidateRobustEntryPoint(context, bufSize))
1900 {
1901 return false;
1902 }
1903
Brandon Jonesd1049182018-03-28 10:02:20 -07001904 GLsizei numParams = 0;
1905
1906 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001907 {
1908 return false;
1909 }
1910
Brandon Jonesd1049182018-03-28 10:02:20 -07001911 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001912 {
1913 return false;
1914 }
1915
Brandon Jonesd1049182018-03-28 10:02:20 -07001916 SetRobustLengthParam(length, numParams);
1917
Geoff Lang2186c382016-10-14 10:54:54 -04001918 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919}
1920
1921bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1922{
1923 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001924 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001926 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001927 return false;
1928 }
Geoff Lang2186c382016-10-14 10:54:54 -04001929 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1930}
1931
1932bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1933 GLuint id,
1934 GLenum pname,
1935 GLsizei bufSize,
1936 GLsizei *length,
1937 GLuint *params)
1938{
1939 if (!context->getExtensions().disjointTimerQuery &&
1940 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001942 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001943 return false;
1944 }
1945
1946 if (!ValidateRobustEntryPoint(context, bufSize))
1947 {
1948 return false;
1949 }
1950
Brandon Jonesd1049182018-03-28 10:02:20 -07001951 GLsizei numParams = 0;
1952
1953 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001954 {
1955 return false;
1956 }
1957
Brandon Jonesd1049182018-03-28 10:02:20 -07001958 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001959 {
1960 return false;
1961 }
1962
Brandon Jonesd1049182018-03-28 10:02:20 -07001963 SetRobustLengthParam(length, numParams);
1964
Geoff Lang2186c382016-10-14 10:54:54 -04001965 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966}
1967
1968bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1969{
1970 if (!context->getExtensions().disjointTimerQuery)
1971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001972 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001973 return false;
1974 }
Geoff Lang2186c382016-10-14 10:54:54 -04001975 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1976}
1977
1978bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1979 GLuint id,
1980 GLenum pname,
1981 GLsizei bufSize,
1982 GLsizei *length,
1983 GLint64 *params)
1984{
1985 if (!context->getExtensions().disjointTimerQuery)
1986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001988 return false;
1989 }
1990
1991 if (!ValidateRobustEntryPoint(context, bufSize))
1992 {
1993 return false;
1994 }
1995
Brandon Jonesd1049182018-03-28 10:02:20 -07001996 GLsizei numParams = 0;
1997
1998 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001999 {
2000 return false;
2001 }
2002
Brandon Jonesd1049182018-03-28 10:02:20 -07002003 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002004 {
2005 return false;
2006 }
2007
Brandon Jonesd1049182018-03-28 10:02:20 -07002008 SetRobustLengthParam(length, numParams);
2009
Geoff Lang2186c382016-10-14 10:54:54 -04002010 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002011}
2012
2013bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2014{
2015 if (!context->getExtensions().disjointTimerQuery)
2016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002017 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002018 return false;
2019 }
Geoff Lang2186c382016-10-14 10:54:54 -04002020 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2021}
2022
2023bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2024 GLuint id,
2025 GLenum pname,
2026 GLsizei bufSize,
2027 GLsizei *length,
2028 GLuint64 *params)
2029{
2030 if (!context->getExtensions().disjointTimerQuery)
2031 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002032 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002033 return false;
2034 }
2035
2036 if (!ValidateRobustEntryPoint(context, bufSize))
2037 {
2038 return false;
2039 }
2040
Brandon Jonesd1049182018-03-28 10:02:20 -07002041 GLsizei numParams = 0;
2042
2043 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002044 {
2045 return false;
2046 }
2047
Brandon Jonesd1049182018-03-28 10:02:20 -07002048 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002049 {
2050 return false;
2051 }
2052
Brandon Jonesd1049182018-03-28 10:02:20 -07002053 SetRobustLengthParam(length, numParams);
2054
Geoff Lang2186c382016-10-14 10:54:54 -04002055 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002056}
2057
Jamie Madill5b772312018-03-08 20:28:32 -05002058bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002059 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002060 GLint location,
2061 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002062 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002063{
Jiajia Qin5451d532017-11-16 17:16:34 +08002064 // TODO(Jiajia): Add image uniform check in future.
2065 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002066 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002067 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002068 return false;
2069 }
2070
Jiajia Qin5451d532017-11-16 17:16:34 +08002071 if (!program)
2072 {
2073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2074 return false;
2075 }
2076
2077 if (!program->isLinked())
2078 {
2079 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2080 return false;
2081 }
2082
2083 if (location == -1)
2084 {
2085 // Silently ignore the uniform command
2086 return false;
2087 }
2088
2089 const auto &uniformLocations = program->getUniformLocations();
2090 size_t castedLocation = static_cast<size_t>(location);
2091 if (castedLocation >= uniformLocations.size())
2092 {
2093 context->handleError(InvalidOperation() << "Invalid uniform location");
2094 return false;
2095 }
2096
2097 const auto &uniformLocation = uniformLocations[castedLocation];
2098 if (uniformLocation.ignored)
2099 {
2100 // Silently ignore the uniform command
2101 return false;
2102 }
2103
2104 if (!uniformLocation.used())
2105 {
2106 context->handleError(InvalidOperation());
2107 return false;
2108 }
2109
2110 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2111
2112 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002113 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002114 {
2115 context->handleError(InvalidOperation());
2116 return false;
2117 }
2118
2119 *uniformOut = &uniform;
2120 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002121}
2122
Jamie Madill5b772312018-03-08 20:28:32 -05002123bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002124 GLenum uniformType,
2125 GLsizei count,
2126 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002127{
Jiajia Qin5451d532017-11-16 17:16:34 +08002128 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2129 // It is compatible with INT or BOOL.
2130 // Do these cheap tests first, for a little extra speed.
2131 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002132 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002133 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002134 }
2135
Jiajia Qin5451d532017-11-16 17:16:34 +08002136 if (IsSamplerType(uniformType))
2137 {
2138 // Check that the values are in range.
2139 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2140 for (GLsizei i = 0; i < count; ++i)
2141 {
2142 if (value[i] < 0 || value[i] >= max)
2143 {
2144 context->handleError(InvalidValue() << "sampler uniform value out of range");
2145 return false;
2146 }
2147 }
2148 return true;
2149 }
2150
2151 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2152 return false;
2153}
2154
Jamie Madill5b772312018-03-08 20:28:32 -05002155bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002156{
2157 // Check that the value type is compatible with uniform type.
2158 // Do the cheaper test first, for a little extra speed.
2159 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2160 {
2161 return true;
2162 }
2163
2164 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2165 return false;
2166}
2167
Jamie Madill5b772312018-03-08 20:28:32 -05002168bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002169{
2170 // Check that the value type is compatible with uniform type.
2171 if (valueType == uniformType)
2172 {
2173 return true;
2174 }
2175
2176 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2177 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002178}
2179
Jamie Madill5b772312018-03-08 20:28:32 -05002180bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002181{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002182 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002183 gl::Program *programObject = context->getGLState().getProgram();
2184 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2185 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002186}
2187
Jamie Madill5b772312018-03-08 20:28:32 -05002188bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002189{
2190 const LinkedUniform *uniform = nullptr;
2191 gl::Program *programObject = context->getGLState().getProgram();
2192 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2193 ValidateUniform1ivValue(context, uniform->type, count, value);
2194}
2195
Jamie Madill5b772312018-03-08 20:28:32 -05002196bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002197 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002198 GLint location,
2199 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002200 GLboolean transpose)
2201{
Geoff Lang92019432017-11-20 13:09:34 -05002202 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002204 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002205 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002206 }
2207
Jamie Madill62d31cb2015-09-11 13:25:51 -04002208 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002209 gl::Program *programObject = context->getGLState().getProgram();
2210 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2211 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002212}
2213
Jamie Madill5b772312018-03-08 20:28:32 -05002214bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002215{
2216 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002218 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002219 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002220 }
2221
Jamie Madill0af26e12015-03-05 19:54:33 -05002222 const Caps &caps = context->getCaps();
2223
Jamie Madill893ab082014-05-16 16:56:10 -04002224 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2225 {
2226 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2227
Jamie Madill0af26e12015-03-05 19:54:33 -05002228 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002230 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002231 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002232 }
2233 }
2234
2235 switch (pname)
2236 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002237 case GL_TEXTURE_BINDING_2D:
2238 case GL_TEXTURE_BINDING_CUBE_MAP:
2239 case GL_TEXTURE_BINDING_3D:
2240 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002241 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002242 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002243 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2244 if (!context->getExtensions().textureRectangle)
2245 {
2246 context->handleError(InvalidEnum()
2247 << "ANGLE_texture_rectangle extension not present");
2248 return false;
2249 }
2250 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002251 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2252 if (!context->getExtensions().eglStreamConsumerExternal &&
2253 !context->getExtensions().eglImageExternal)
2254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002255 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2256 "nor GL_OES_EGL_image_external "
2257 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002258 return false;
2259 }
2260 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002261
He Yunchaoced53ae2016-11-29 15:00:51 +08002262 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2263 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002264 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002265 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2266 ASSERT(readFramebuffer);
2267
Jamie Madill427064d2018-04-13 16:20:34 -04002268 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002269 {
Geoff Langb1196682014-07-23 13:47:29 -04002270 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002271 }
2272
Jamie Madille98b1b52018-03-08 09:47:23 -05002273 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002274 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002275 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002276 return false;
2277 }
2278
Jamie Madille98b1b52018-03-08 09:47:23 -05002279 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002280 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002282 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002283 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002284 }
2285 }
2286 break;
2287
He Yunchaoced53ae2016-11-29 15:00:51 +08002288 default:
2289 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002290 }
2291
2292 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002293 if (*numParams == 0)
2294 {
2295 return false;
2296 }
2297
2298 return true;
2299}
2300
Brandon Jonesd1049182018-03-28 10:02:20 -07002301bool ValidateGetBooleanvRobustANGLE(Context *context,
2302 GLenum pname,
2303 GLsizei bufSize,
2304 GLsizei *length,
2305 GLboolean *params)
2306{
2307 GLenum nativeType;
2308 unsigned int numParams = 0;
2309
2310 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2311 {
2312 return false;
2313 }
2314
2315 SetRobustLengthParam(length, numParams);
2316
2317 return true;
2318}
2319
2320bool ValidateGetFloatvRobustANGLE(Context *context,
2321 GLenum pname,
2322 GLsizei bufSize,
2323 GLsizei *length,
2324 GLfloat *params)
2325{
2326 GLenum nativeType;
2327 unsigned int numParams = 0;
2328
2329 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2330 {
2331 return false;
2332 }
2333
2334 SetRobustLengthParam(length, numParams);
2335
2336 return true;
2337}
2338
2339bool ValidateGetIntegervRobustANGLE(Context *context,
2340 GLenum pname,
2341 GLsizei bufSize,
2342 GLsizei *length,
2343 GLint *data)
2344{
2345 GLenum nativeType;
2346 unsigned int numParams = 0;
2347
2348 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2349 {
2350 return false;
2351 }
2352
2353 SetRobustLengthParam(length, numParams);
2354
2355 return true;
2356}
2357
2358bool ValidateGetInteger64vRobustANGLE(Context *context,
2359 GLenum pname,
2360 GLsizei bufSize,
2361 GLsizei *length,
2362 GLint64 *data)
2363{
2364 GLenum nativeType;
2365 unsigned int numParams = 0;
2366
2367 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2368 {
2369 return false;
2370 }
2371
2372 if (nativeType == GL_INT_64_ANGLEX)
2373 {
2374 CastStateValues(context, nativeType, pname, numParams, data);
2375 return false;
2376 }
2377
2378 SetRobustLengthParam(length, numParams);
2379 return true;
2380}
2381
Jamie Madill5b772312018-03-08 20:28:32 -05002382bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002383 GLenum pname,
2384 GLsizei bufSize,
2385 GLenum *nativeType,
2386 unsigned int *numParams)
2387{
2388 if (!ValidateRobustEntryPoint(context, bufSize))
2389 {
2390 return false;
2391 }
2392
2393 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2394 {
2395 return false;
2396 }
2397
2398 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002399 {
2400 return false;
2401 }
2402
2403 return true;
2404}
2405
Jamie Madill5b772312018-03-08 20:28:32 -05002406bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002407 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002408 GLint level,
2409 GLenum internalformat,
2410 bool isSubImage,
2411 GLint xoffset,
2412 GLint yoffset,
2413 GLint zoffset,
2414 GLint x,
2415 GLint y,
2416 GLsizei width,
2417 GLsizei height,
2418 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002419 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002420{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002421 TextureType texType = TextureTargetToType(target);
2422
Brandon Jones6cad5662017-06-14 13:25:13 -07002423 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002425 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2426 return false;
2427 }
2428
2429 if (width < 0 || height < 0)
2430 {
2431 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002432 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002433 }
2434
He Yunchaoced53ae2016-11-29 15:00:51 +08002435 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2436 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002438 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002439 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002440 }
2441
2442 if (border != 0)
2443 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002444 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002445 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002446 }
2447
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002448 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002449 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002450 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002451 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002452 }
2453
Jamie Madille98b1b52018-03-08 09:47:23 -05002454 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002455 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002456 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002457 {
Geoff Langb1196682014-07-23 13:47:29 -04002458 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002459 }
2460
Jamie Madille98b1b52018-03-08 09:47:23 -05002461 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002462 {
Geoff Langb1196682014-07-23 13:47:29 -04002463 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002464 }
2465
Martin Radev138064f2016-07-15 12:03:41 +03002466 if (readFramebuffer->getReadBufferState() == GL_NONE)
2467 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002469 return false;
2470 }
2471
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002472 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2473 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002474 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002475 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002476 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2477 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002478 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002479 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002480 return false;
2481 }
2482
Martin Radev04e2c3b2017-07-27 16:54:35 +03002483 // ANGLE_multiview spec, Revision 1:
2484 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2485 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002486 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2487 // framebuffer is more than one.
2488 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002489 {
2490 context->handleError(InvalidFramebufferOperation()
2491 << "The active read framebuffer object has multiview attachments.");
2492 return false;
2493 }
2494
Geoff Langaae65a42014-05-26 12:43:44 -04002495 const gl::Caps &caps = context->getCaps();
2496
Geoff Langaae65a42014-05-26 12:43:44 -04002497 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002498 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002499 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002500 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002501 maxDimension = caps.max2DTextureSize;
2502 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002503
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002504 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 maxDimension = caps.maxCubeMapTextureSize;
2506 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002507
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002508 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002509 maxDimension = caps.maxRectangleTextureSize;
2510 break;
2511
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002512 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002513 maxDimension = caps.max2DTextureSize;
2514 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002515
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002516 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002517 maxDimension = caps.max3DTextureSize;
2518 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002519
He Yunchaoced53ae2016-11-29 15:00:51 +08002520 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002521 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002522 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002523 }
2524
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002525 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002526 if (!texture)
2527 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002528 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002529 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002530 }
2531
Geoff Lang69cce582015-09-17 13:20:36 -04002532 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002534 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002535 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002536 }
2537
Geoff Langca271392017-04-05 12:30:00 -04002538 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002539 isSubImage ? *texture->getFormat(target, level).info
2540 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002541
Geoff Lang966c9402017-04-18 12:38:27 -04002542 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002544 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002545 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002546 }
2547
2548 if (isSubImage)
2549 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002550 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2551 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2552 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002554 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002555 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002556 }
2557 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002558 else
2559 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002560 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002561 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002562 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002563 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002564 }
2565
Geoff Langeb66a6e2016-10-31 13:06:12 -04002566 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002567 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002568 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002569 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002570 }
2571
2572 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002573 if (static_cast<int>(width) > maxLevelDimension ||
2574 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002575 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002576 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002577 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002578 }
2579 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002580
Jamie Madill0c8abca2016-07-22 20:21:26 -04002581 if (textureFormatOut)
2582 {
2583 *textureFormatOut = texture->getFormat(target, level);
2584 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002585
2586 // Detect texture copying feedback loops for WebGL.
2587 if (context->getExtensions().webglCompatibility)
2588 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002589 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002590 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002591 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002592 return false;
2593 }
2594 }
2595
Jamie Madill560a8d82014-05-21 13:06:20 -04002596 return true;
2597}
2598
Jamie Madill493f9572018-05-24 19:52:15 -04002599bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002600{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002601 const Extensions &extensions = context->getExtensions();
2602
Jamie Madill1aeb1312014-06-20 13:21:25 -04002603 switch (mode)
2604 {
Jamie Madill493f9572018-05-24 19:52:15 -04002605 case PrimitiveMode::Points:
2606 case PrimitiveMode::Lines:
2607 case PrimitiveMode::LineLoop:
2608 case PrimitiveMode::LineStrip:
2609 case PrimitiveMode::Triangles:
2610 case PrimitiveMode::TriangleStrip:
2611 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002612 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002613
Jamie Madill493f9572018-05-24 19:52:15 -04002614 case PrimitiveMode::LinesAdjacency:
2615 case PrimitiveMode::LineStripAdjacency:
2616 case PrimitiveMode::TrianglesAdjacency:
2617 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002618 if (!extensions.geometryShader)
2619 {
2620 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2621 return false;
2622 }
2623 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002624 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002625 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002626 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002627 }
2628
Jamie Madill250d33f2014-06-06 17:09:03 -04002629 if (count < 0)
2630 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002631 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002632 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002633 }
2634
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002635 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002636
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002637 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2638 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2639 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2640 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002641 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002642 // Check for mapped buffers
2643 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002644 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002645 {
2646 context->handleError(InvalidOperation());
2647 return false;
2648 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002649 }
2650
Jamie Madillcbcde722017-01-06 14:50:00 -05002651 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2652 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002653 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002654 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002655 {
Ken Russellb9f92502018-01-27 19:00:26 -08002656 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002657 const FramebufferAttachment *dsAttachment =
2658 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002659 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2660 ASSERT(stencilBits <= 8);
2661
Jinyoung Hur85769f02015-10-20 17:08:44 -04002662 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002663 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002664 {
Ken Russellb9f92502018-01-27 19:00:26 -08002665 GLuint maxStencilValue = (1 << stencilBits) - 1;
2666
2667 bool differentRefs =
2668 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2669 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2670 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2671 (depthStencilState.stencilBackWritemask & maxStencilValue);
2672 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2673 (depthStencilState.stencilBackMask & maxStencilValue);
2674
2675 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002676 {
Ken Russellb9f92502018-01-27 19:00:26 -08002677 if (!extensions.webglCompatibility)
2678 {
Jamie Madilla2f043d2018-07-10 17:21:20 -04002679 WARN() << "This ANGLE implementation does not support separate front/back "
2680 "stencil writemasks, reference values, or stencil mask values.";
Ken Russellb9f92502018-01-27 19:00:26 -08002681 }
2682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2683 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002684 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002685 }
Jamie Madillac528012014-06-20 13:21:23 -04002686 }
2687
Jamie Madill427064d2018-04-13 16:20:34 -04002688 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002689 {
Geoff Langb1196682014-07-23 13:47:29 -04002690 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002691 }
2692
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002693 // If we are running GLES1, there is no current program.
2694 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002695 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002696
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002697 gl::Program *program = state.getProgram();
2698 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002699 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002700 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002701 return false;
2702 }
Martin Radev7e69f762017-07-27 14:54:13 +03002703
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002704 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2705 // vertex shader stage or fragment shader stage is a undefined behaviour.
2706 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2707 // produce undefined result.
2708 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2709 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002710 {
2711 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002712 << "It is a undefined behaviour to render without "
2713 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002714 return false;
2715 }
Martin Radevffe754b2017-07-31 10:38:07 +03002716
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002717 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002718 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002719 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002720 return false;
2721 }
2722
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002723 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002724 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002725 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2726 const int framebufferNumViews = framebuffer->getNumViews();
2727 if (framebufferNumViews != programNumViews)
2728 {
2729 context->handleError(InvalidOperation()
2730 << "The number of views in the active program "
2731 "and draw framebuffer does not match.");
2732 return false;
2733 }
2734
2735 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2736 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2737 framebufferNumViews > 1)
2738 {
2739 context->handleError(InvalidOperation()
2740 << "There is an active transform feedback object "
2741 "when the number of views in the active draw "
2742 "framebuffer is greater than 1.");
2743 return false;
2744 }
2745
2746 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2747 state.isQueryActive(QueryType::TimeElapsed))
2748 {
2749 context->handleError(InvalidOperation()
2750 << "There is an active query for target "
2751 "GL_TIME_ELAPSED_EXT when the number of "
2752 "views in the active draw framebuffer is "
2753 "greater than 1.");
2754 return false;
2755 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002756 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002757
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002758 // Do geometry shader specific validations
2759 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002760 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002761 if (!IsCompatibleDrawModeWithGeometryShader(
2762 mode, program->getGeometryShaderInputPrimitiveType()))
2763 {
2764 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2765 IncompatibleDrawModeAgainstGeometryShader);
2766 return false;
2767 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002768 }
Geoff Lange0cff192017-05-30 13:04:56 -04002769
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002770 // Uniform buffer validation
2771 for (unsigned int uniformBlockIndex = 0;
2772 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002773 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002774 const gl::InterfaceBlock &uniformBlock =
2775 program->getUniformBlockByIndex(uniformBlockIndex);
2776 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2777 const OffsetBindingPointer<Buffer> &uniformBuffer =
2778 state.getIndexedUniformBuffer(blockBinding);
2779
2780 if (uniformBuffer.get() == nullptr)
2781 {
2782 // undefined behaviour
2783 context->handleError(
2784 InvalidOperation()
2785 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2786 return false;
2787 }
2788
2789 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2790 if (uniformBufferSize < uniformBlock.dataSize)
2791 {
2792 // undefined behaviour
2793 context->handleError(
2794 InvalidOperation()
2795 << "It is undefined behaviour to use a uniform buffer that is too small.");
2796 return false;
2797 }
2798
2799 if (extensions.webglCompatibility &&
2800 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2801 {
2802 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2803 UniformBufferBoundForTransformFeedback);
2804 return false;
2805 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002806 }
2807
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002808 // Do some additonal WebGL-specific validation
2809 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002810 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002811 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2812 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2813 transformFeedbackObject->buffersBoundForOtherUse())
2814 {
2815 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2816 TransformFeedbackBufferDoubleBound);
2817 return false;
2818 }
2819 // Detect rendering feedback loops for WebGL.
2820 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2821 {
2822 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2823 return false;
2824 }
2825
2826 // Detect that the vertex shader input types match the attribute types
2827 if (!ValidateVertexShaderAttributeTypeMatch(context))
2828 {
2829 return false;
2830 }
2831
2832 // Detect that the color buffer types match the fragment shader output types
2833 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2834 {
2835 return false;
2836 }
Jamie Madillac43aaa2018-07-31 11:22:13 -04002837
2838 if (count > 0)
2839 {
2840 const VertexArray *vao = context->getGLState().getVertexArray();
2841 if (vao->hasTransformFeedbackBindingConflict(context))
2842 {
2843 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2844 VertexBufferBoundForTransformFeedback);
2845 return false;
2846 }
2847 }
Geoff Lange0cff192017-05-30 13:04:56 -04002848 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002849 }
2850
Jamie Madill9fdaa492018-02-16 10:52:11 -05002851 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002852}
2853
Jamie Madill5b772312018-03-08 20:28:32 -05002854bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002855 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002856 GLint first,
2857 GLsizei count,
2858 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002859{
Jamie Madillfd716582014-06-06 17:09:04 -04002860 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002861 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002862 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002863 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002864 }
2865
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002866 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002867 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002868 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002869 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002870 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002871 if (!ValidateTransformFeedbackPrimitiveMode(context,
2872 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002873 {
James Darpinian30b604d2018-03-12 17:26:57 -07002874 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2875 return false;
2876 }
2877
2878 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2879 {
2880 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2881 return false;
2882 }
Jamie Madillfd716582014-06-06 17:09:04 -04002883 }
2884
Jiajia Qind9671222016-11-29 16:30:31 +08002885 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002886 {
2887 return false;
2888 }
2889
Corentin Wallez71168a02016-12-19 15:11:18 -08002890 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002891 // - first < 0 has been checked as an error condition.
2892 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002893 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002894 ASSERT(first >= 0);
2895 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002896 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002897 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2898 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2899 {
2900 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2901 return false;
2902 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002903
Jamie Madill9fdaa492018-02-16 10:52:11 -05002904 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2905 {
2906 return false;
2907 }
Jamie Madillfd716582014-06-06 17:09:04 -04002908 }
2909
2910 return true;
2911}
2912
He Yunchaoced53ae2016-11-29 15:00:51 +08002913bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002914 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002915 GLint first,
2916 GLsizei count,
2917 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002918{
Geoff Lang63c5a592017-09-27 14:08:16 -04002919 if (!context->getExtensions().instancedArrays)
2920 {
2921 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2922 return false;
2923 }
2924
Corentin Wallez170efbf2017-05-02 13:45:01 -04002925 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002926 {
2927 return false;
2928 }
2929
Corentin Wallez0dc97812017-06-22 14:38:44 -04002930 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002931}
2932
Jamie Madill493f9572018-05-24 19:52:15 -04002933bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002934{
Jamie Madill250d33f2014-06-06 17:09:03 -04002935 switch (type)
2936 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002937 case GL_UNSIGNED_BYTE:
2938 case GL_UNSIGNED_SHORT:
2939 break;
2940 case GL_UNSIGNED_INT:
2941 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002943 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002944 return false;
2945 }
2946 break;
2947 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002949 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002950 }
2951
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002952 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002953
2954 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002955 if (curTransformFeedback && curTransformFeedback->isActive() &&
2956 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002957 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002958 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2959 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2960 if (context->getExtensions().geometryShader)
2961 {
2962 if (!ValidateTransformFeedbackPrimitiveMode(
2963 context, curTransformFeedback->getPrimitiveMode(), mode))
2964 {
2965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2966 return false;
2967 }
2968 }
2969 else
2970 {
2971 // It is an invalid operation to call DrawElements, DrawRangeElements or
2972 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2973 // 86)
2974 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2975 UnsupportedDrawModeForTransformFeedback);
2976 return false;
2977 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002978 }
2979
Jiajia Qind9671222016-11-29 16:30:31 +08002980 return true;
2981}
2982
Jamie Madill5b772312018-03-08 20:28:32 -05002983bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002984 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002985 GLsizei count,
2986 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002987 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002988 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002989{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002990 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08002991 return false;
2992
2993 const State &state = context->getGLState();
2994
Corentin Wallez170efbf2017-05-02 13:45:01 -04002995 if (!ValidateDrawBase(context, mode, count))
2996 {
2997 return false;
2998 }
2999
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003000 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
3001 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3002 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3003 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04003004 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003005 // Check for mapped buffers
3006 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04003007 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003008 {
3009 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3010 return false;
3011 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003012 }
3013
He Yunchaoced53ae2016-11-29 15:00:51 +08003014 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003015 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003016
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003017 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3018
3019 if (context->getExtensions().webglCompatibility)
3020 {
3021 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3022 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3023 {
3024 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3025 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3026 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003027 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003028 return false;
3029 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003030
3031 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3032 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3033 // error is generated.
3034 if (reinterpret_cast<intptr_t>(indices) < 0)
3035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003036 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003037 return false;
3038 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003039 }
3040
3041 if (context->getExtensions().webglCompatibility ||
3042 !context->getGLState().areClientArraysEnabled())
3043 {
Brandon Jones2a018152018-06-08 15:59:26 -07003044 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003045 {
3046 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003047 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3048 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003049 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003050 return false;
3051 }
3052 }
3053
Jamie Madill9fdaa492018-02-16 10:52:11 -05003054 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003055 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003056 // This is an application error that would normally result in a crash, but we catch it and
3057 // return an error
3058 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3059 return false;
3060 }
3061
3062 if (count > 0 && elementArrayBuffer)
3063 {
3064 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3065 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3066 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3067 constexpr uint64_t kMaxTypeSize = 8;
3068 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3069 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3070 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3071
3072 uint64_t typeSize = typeBytes;
3073 uint64_t elementCount = static_cast<uint64_t>(count);
3074 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3075
3076 // Doing the multiplication here is overflow-safe
3077 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3078
3079 // The offset can be any value, check for overflows
3080 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3081 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003082 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3084 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003085 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003086
3087 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3088 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003089 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003090 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3091 return false;
3092 }
3093
3094 ASSERT(isPow2(typeSize) && typeSize > 0);
3095 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3096 {
3097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003098 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003099 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003100
3101 if (context->getExtensions().webglCompatibility &&
3102 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3103 {
3104 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3105 ElementArrayBufferBoundForTransformFeedback);
3106 return false;
3107 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003108 }
3109
Jamie Madillac43aaa2018-07-31 11:22:13 -04003110 if (context->getExtensions().robustBufferAccessBehavior || count == 0)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003111 {
Jamie Madillac43aaa2018-07-31 11:22:13 -04003112 // Special checks are needed for client attribs. But we don't need to validate overflows.
3113 if (!ValidateDrawClientAttribs(context))
Jamie Madill9fdaa492018-02-16 10:52:11 -05003114 {
3115 return false;
3116 }
3117 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003118 else
3119 {
3120 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003121 const DrawCallParams &params = context->getParams<DrawCallParams>();
3122 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3123 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003124
3125 // If we use an index greater than our maximum supported index range, return an error.
3126 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3127 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003128 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003129 {
3130 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3131 return false;
3132 }
3133
Jamie Madill6f5444d2018-03-14 10:08:11 -04003134 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3135 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003136 {
3137 return false;
3138 }
3139
3140 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003141 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003142 }
3143
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003144 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003145}
3146
Jamie Madill5b772312018-03-08 20:28:32 -05003147bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003148 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003149 GLsizei count,
3150 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003151 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003152 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003153{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003154 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003155}
3156
Geoff Lang3edfe032015-09-04 16:38:24 -04003157bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003158 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003159 GLsizei count,
3160 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003161 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003162 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003163{
Geoff Lang63c5a592017-09-27 14:08:16 -04003164 if (!context->getExtensions().instancedArrays)
3165 {
3166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3167 return false;
3168 }
3169
Corentin Wallez170efbf2017-05-02 13:45:01 -04003170 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003171 {
3172 return false;
3173 }
3174
Corentin Wallez0dc97812017-06-22 14:38:44 -04003175 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003176}
3177
He Yunchaoced53ae2016-11-29 15:00:51 +08003178bool ValidateFramebufferTextureBase(Context *context,
3179 GLenum target,
3180 GLenum attachment,
3181 GLuint texture,
3182 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003183{
Geoff Lange8afa902017-09-27 15:00:43 -04003184 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003187 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003188 }
3189
3190 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003191 {
3192 return false;
3193 }
3194
Jamie Madill55ec3b12014-07-03 10:38:57 -04003195 if (texture != 0)
3196 {
3197 gl::Texture *tex = context->getTexture(texture);
3198
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003199 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003201 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003202 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003203 }
3204
3205 if (level < 0)
3206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003207 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003208 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003209 }
3210 }
3211
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003212 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003213 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003214
Jamie Madill84115c92015-04-23 15:00:07 -04003215 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003216 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003218 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003219 }
3220
3221 return true;
3222}
3223
Geoff Langb1196682014-07-23 13:47:29 -04003224bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003225{
3226 if (program == 0)
3227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003228 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003229 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003230 }
3231
Dian Xiang769769a2015-09-09 15:20:08 -07003232 gl::Program *programObject = GetValidProgram(context, program);
3233 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003234 {
3235 return false;
3236 }
3237
Jamie Madill0063c512014-08-25 15:47:53 -04003238 if (!programObject || !programObject->isLinked())
3239 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003240 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003241 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003242 }
3243
Geoff Lang7dd2e102014-11-10 15:19:26 -05003244 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003246 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003247 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003248 }
3249
Jamie Madill0063c512014-08-25 15:47:53 -04003250 return true;
3251}
3252
Geoff Langf41d0ee2016-10-07 13:04:23 -04003253static bool ValidateSizedGetUniform(Context *context,
3254 GLuint program,
3255 GLint location,
3256 GLsizei bufSize,
3257 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003258{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003259 if (length)
3260 {
3261 *length = 0;
3262 }
3263
Jamie Madill78f41802014-08-25 15:47:55 -04003264 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003265 {
Jamie Madill78f41802014-08-25 15:47:55 -04003266 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003267 }
3268
Geoff Langf41d0ee2016-10-07 13:04:23 -04003269 if (bufSize < 0)
3270 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003271 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003272 return false;
3273 }
3274
Jamie Madilla502c742014-08-28 17:19:13 -04003275 gl::Program *programObject = context->getProgram(program);
3276 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003277
Jamie Madill78f41802014-08-25 15:47:55 -04003278 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003279 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003280 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003281 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003282 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003284 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003285 }
3286
Geoff Langf41d0ee2016-10-07 13:04:23 -04003287 if (length)
3288 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003289 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003290 }
3291
Jamie Madill0063c512014-08-25 15:47:53 -04003292 return true;
3293}
3294
He Yunchaoced53ae2016-11-29 15:00:51 +08003295bool ValidateGetnUniformfvEXT(Context *context,
3296 GLuint program,
3297 GLint location,
3298 GLsizei bufSize,
3299 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003300{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003301 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003302}
3303
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003304bool ValidateGetnUniformfvRobustANGLE(Context *context,
3305 GLuint program,
3306 GLint location,
3307 GLsizei bufSize,
3308 GLsizei *length,
3309 GLfloat *params)
3310{
3311 UNIMPLEMENTED();
3312 return false;
3313}
3314
He Yunchaoced53ae2016-11-29 15:00:51 +08003315bool ValidateGetnUniformivEXT(Context *context,
3316 GLuint program,
3317 GLint location,
3318 GLsizei bufSize,
3319 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003320{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003321 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3322}
3323
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003324bool ValidateGetnUniformivRobustANGLE(Context *context,
3325 GLuint program,
3326 GLint location,
3327 GLsizei bufSize,
3328 GLsizei *length,
3329 GLint *params)
3330{
3331 UNIMPLEMENTED();
3332 return false;
3333}
3334
3335bool ValidateGetnUniformuivRobustANGLE(Context *context,
3336 GLuint program,
3337 GLint location,
3338 GLsizei bufSize,
3339 GLsizei *length,
3340 GLuint *params)
3341{
3342 UNIMPLEMENTED();
3343 return false;
3344}
3345
Geoff Langf41d0ee2016-10-07 13:04:23 -04003346bool ValidateGetUniformfvRobustANGLE(Context *context,
3347 GLuint program,
3348 GLint location,
3349 GLsizei bufSize,
3350 GLsizei *length,
3351 GLfloat *params)
3352{
3353 if (!ValidateRobustEntryPoint(context, bufSize))
3354 {
3355 return false;
3356 }
3357
Brandon Jonesd1049182018-03-28 10:02:20 -07003358 GLsizei writeLength = 0;
3359
Geoff Langf41d0ee2016-10-07 13:04:23 -04003360 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003361 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3362 {
3363 return false;
3364 }
3365
3366 SetRobustLengthParam(length, writeLength);
3367
3368 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003369}
3370
3371bool ValidateGetUniformivRobustANGLE(Context *context,
3372 GLuint program,
3373 GLint location,
3374 GLsizei bufSize,
3375 GLsizei *length,
3376 GLint *params)
3377{
3378 if (!ValidateRobustEntryPoint(context, bufSize))
3379 {
3380 return false;
3381 }
3382
Brandon Jonesd1049182018-03-28 10:02:20 -07003383 GLsizei writeLength = 0;
3384
Geoff Langf41d0ee2016-10-07 13:04:23 -04003385 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003386 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3387 {
3388 return false;
3389 }
3390
3391 SetRobustLengthParam(length, writeLength);
3392
3393 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003394}
3395
3396bool ValidateGetUniformuivRobustANGLE(Context *context,
3397 GLuint program,
3398 GLint location,
3399 GLsizei bufSize,
3400 GLsizei *length,
3401 GLuint *params)
3402{
3403 if (!ValidateRobustEntryPoint(context, bufSize))
3404 {
3405 return false;
3406 }
3407
3408 if (context->getClientMajorVersion() < 3)
3409 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003410 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003411 return false;
3412 }
3413
Brandon Jonesd1049182018-03-28 10:02:20 -07003414 GLsizei writeLength = 0;
3415
Geoff Langf41d0ee2016-10-07 13:04:23 -04003416 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003417 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3418 {
3419 return false;
3420 }
3421
3422 SetRobustLengthParam(length, writeLength);
3423
3424 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003425}
3426
He Yunchaoced53ae2016-11-29 15:00:51 +08003427bool ValidateDiscardFramebufferBase(Context *context,
3428 GLenum target,
3429 GLsizei numAttachments,
3430 const GLenum *attachments,
3431 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003432{
3433 if (numAttachments < 0)
3434 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003435 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003436 return false;
3437 }
3438
3439 for (GLsizei i = 0; i < numAttachments; ++i)
3440 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003441 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003442 {
3443 if (defaultFramebuffer)
3444 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003445 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003446 return false;
3447 }
3448
3449 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003451 context->handleError(InvalidOperation() << "Requested color attachment is "
3452 "greater than the maximum supported "
3453 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003454 return false;
3455 }
3456 }
3457 else
3458 {
3459 switch (attachments[i])
3460 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003461 case GL_DEPTH_ATTACHMENT:
3462 case GL_STENCIL_ATTACHMENT:
3463 case GL_DEPTH_STENCIL_ATTACHMENT:
3464 if (defaultFramebuffer)
3465 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003466 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3467 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003468 return false;
3469 }
3470 break;
3471 case GL_COLOR:
3472 case GL_DEPTH:
3473 case GL_STENCIL:
3474 if (!defaultFramebuffer)
3475 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003476 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3477 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003478 return false;
3479 }
3480 break;
3481 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003483 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003484 }
3485 }
3486 }
3487
3488 return true;
3489}
3490
Austin Kinross6ee1e782015-05-29 17:05:37 -07003491bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3492{
Jamie Madill007530e2017-12-28 14:27:04 -05003493 if (!context->getExtensions().debugMarker)
3494 {
3495 // The debug marker calls should not set error state
3496 // However, it seems reasonable to set an error state if the extension is not enabled
3497 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3498 return false;
3499 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003500
Jamie Madill007530e2017-12-28 14:27:04 -05003501 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003502 if (length < 0)
3503 {
3504 return false;
3505 }
3506
3507 if (marker == nullptr)
3508 {
3509 return false;
3510 }
3511
3512 return true;
3513}
3514
3515bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3516{
Jamie Madill007530e2017-12-28 14:27:04 -05003517 if (!context->getExtensions().debugMarker)
3518 {
3519 // The debug marker calls should not set error state
3520 // However, it seems reasonable to set an error state if the extension is not enabled
3521 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3522 return false;
3523 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003524
Jamie Madill007530e2017-12-28 14:27:04 -05003525 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003526 if (length < 0)
3527 {
3528 return false;
3529 }
3530
3531 if (length > 0 && marker == nullptr)
3532 {
3533 return false;
3534 }
3535
3536 return true;
3537}
3538
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003539bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003540{
Geoff Langa8406172015-07-21 16:53:39 -04003541 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003543 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003544 return false;
3545 }
3546
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003547 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003548 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003549 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003550 if (!context->getExtensions().eglImage)
3551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003552 context->handleError(InvalidEnum()
3553 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003554 }
3555 break;
3556
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003557 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003558 if (!context->getExtensions().eglImageExternal)
3559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003560 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3561 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003562 }
Geoff Langa8406172015-07-21 16:53:39 -04003563 break;
3564
3565 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003566 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003567 return false;
3568 }
3569
Rafael Cintron05a449a2018-06-20 18:08:04 -07003570 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003571
Jamie Madill61e16b42017-06-19 11:13:23 -04003572 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003573 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003575 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003576 return false;
3577 }
3578
Jamie Madill007530e2017-12-28 14:27:04 -05003579 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003581 context->handleError(InvalidOperation()
3582 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003583 return false;
3584 }
3585
Geoff Langca271392017-04-05 12:30:00 -04003586 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003587 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003588 if (!textureCaps.texturable)
3589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003590 context->handleError(InvalidOperation()
3591 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003592 return false;
3593 }
3594
Geoff Langdcab33b2015-07-21 13:03:16 -04003595 return true;
3596}
3597
3598bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003599 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003600 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003601{
Geoff Langa8406172015-07-21 16:53:39 -04003602 if (!context->getExtensions().eglImage)
3603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003604 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003605 return false;
3606 }
3607
3608 switch (target)
3609 {
3610 case GL_RENDERBUFFER:
3611 break;
3612
3613 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003614 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003615 return false;
3616 }
3617
Rafael Cintron05a449a2018-06-20 18:08:04 -07003618 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003619
Jamie Madill61e16b42017-06-19 11:13:23 -04003620 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003621 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003623 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003624 return false;
3625 }
3626
Geoff Langca271392017-04-05 12:30:00 -04003627 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003628 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003629 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003630 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003631 context->handleError(InvalidOperation()
3632 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003633 return false;
3634 }
3635
Geoff Langdcab33b2015-07-21 13:03:16 -04003636 return true;
3637}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003638
3639bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3640{
Geoff Lang36167ab2015-12-07 10:27:14 -05003641 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003642 {
3643 // The default VAO should always exist
3644 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003645 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003646 return false;
3647 }
3648
3649 return true;
3650}
3651
Geoff Langc5629752015-12-07 16:29:04 -05003652bool ValidateProgramBinaryBase(Context *context,
3653 GLuint program,
3654 GLenum binaryFormat,
3655 const void *binary,
3656 GLint length)
3657{
3658 Program *programObject = GetValidProgram(context, program);
3659 if (programObject == nullptr)
3660 {
3661 return false;
3662 }
3663
3664 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3665 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3666 programBinaryFormats.end())
3667 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003668 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003669 return false;
3670 }
3671
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003672 if (context->hasActiveTransformFeedback(program))
3673 {
3674 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003675 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3676 "is associated with an active transform "
3677 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003678 return false;
3679 }
3680
Geoff Langc5629752015-12-07 16:29:04 -05003681 return true;
3682}
3683
3684bool ValidateGetProgramBinaryBase(Context *context,
3685 GLuint program,
3686 GLsizei bufSize,
3687 GLsizei *length,
3688 GLenum *binaryFormat,
3689 void *binary)
3690{
3691 Program *programObject = GetValidProgram(context, program);
3692 if (programObject == nullptr)
3693 {
3694 return false;
3695 }
3696
3697 if (!programObject->isLinked())
3698 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003700 return false;
3701 }
3702
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003703 if (context->getCaps().programBinaryFormats.empty())
3704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003705 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003706 return false;
3707 }
3708
Geoff Langc5629752015-12-07 16:29:04 -05003709 return true;
3710}
Jamie Madillc29968b2016-01-20 11:17:23 -05003711
Jamie Madill5b772312018-03-08 20:28:32 -05003712bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003713{
3714 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003715 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003716 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003717 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3718 return false;
3719 }
3720 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3721 {
3722 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003723 return false;
3724 }
3725
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003726 ASSERT(context->getGLState().getDrawFramebuffer());
3727 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003728 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3729
3730 // This should come first before the check for the default frame buffer
3731 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3732 // rather than INVALID_OPERATION
3733 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3734 {
3735 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3736
3737 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003738 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3739 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003740 {
3741 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003742 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3743 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3744 // 3.1 is still a bit ambiguous about the error, but future specs are
3745 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003746 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003747 return false;
3748 }
3749 else if (bufs[colorAttachment] >= maxColorAttachment)
3750 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003751 context->handleError(InvalidOperation()
3752 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003753 return false;
3754 }
3755 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3756 frameBufferId != 0)
3757 {
3758 // INVALID_OPERATION-GL is bound to buffer and ith argument
3759 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003760 context->handleError(InvalidOperation()
3761 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003762 return false;
3763 }
3764 }
3765
3766 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3767 // and n is not 1 or bufs is bound to value other than BACK and NONE
3768 if (frameBufferId == 0)
3769 {
3770 if (n != 1)
3771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003772 context->handleError(InvalidOperation()
3773 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003774 return false;
3775 }
3776
3777 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3778 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003779 context->handleError(
3780 InvalidOperation()
3781 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003782 return false;
3783 }
3784 }
3785
3786 return true;
3787}
3788
Geoff Lang496c02d2016-10-20 11:38:11 -07003789bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003790 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003791 GLenum pname,
3792 GLsizei *length,
3793 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003794{
Geoff Lang496c02d2016-10-20 11:38:11 -07003795 if (length)
3796 {
3797 *length = 0;
3798 }
3799
3800 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3801 {
3802 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003803 InvalidOperation()
3804 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003805 return false;
3806 }
3807
Corentin Walleze4477002017-12-01 14:39:58 -05003808 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003809 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003810 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003811 return false;
3812 }
3813
Geoff Lang496c02d2016-10-20 11:38:11 -07003814 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003815 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003816 case GL_BUFFER_MAP_POINTER:
3817 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003818
Geoff Lang496c02d2016-10-20 11:38:11 -07003819 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003820 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003821 return false;
3822 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003823
3824 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3825 // target bound to zero generate an INVALID_OPERATION error."
3826 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003827 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003829 context->handleError(InvalidOperation()
3830 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003831 return false;
3832 }
3833
Geoff Lang496c02d2016-10-20 11:38:11 -07003834 if (length)
3835 {
3836 *length = 1;
3837 }
3838
Olli Etuaho4f667482016-03-30 15:56:35 +03003839 return true;
3840}
3841
Corentin Wallez336129f2017-10-17 15:55:40 -04003842bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003843{
Corentin Walleze4477002017-12-01 14:39:58 -05003844 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003845 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003846 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003847 return false;
3848 }
3849
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003850 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003851
3852 if (buffer == nullptr || !buffer->isMapped())
3853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003854 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003855 return false;
3856 }
3857
3858 return true;
3859}
3860
3861bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003862 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 GLintptr offset,
3864 GLsizeiptr length,
3865 GLbitfield access)
3866{
Corentin Walleze4477002017-12-01 14:39:58 -05003867 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003868 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003869 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003870 return false;
3871 }
3872
Brandon Jones6cad5662017-06-14 13:25:13 -07003873 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003874 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003875 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3876 return false;
3877 }
3878
3879 if (length < 0)
3880 {
3881 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 return false;
3883 }
3884
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003885 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003886
3887 if (!buffer)
3888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003889 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003890 return false;
3891 }
3892
3893 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003894 CheckedNumeric<size_t> checkedOffset(offset);
3895 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003896
Jamie Madille2e406c2016-06-02 13:04:10 -04003897 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003899 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 return false;
3901 }
3902
3903 // Check for invalid bits in the mask
3904 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3905 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3906 GL_MAP_UNSYNCHRONIZED_BIT;
3907
3908 if (access & ~(allAccessBits))
3909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003910 context->handleError(InvalidValue()
3911 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003912 return false;
3913 }
3914
3915 if (length == 0)
3916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003917 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003918 return false;
3919 }
3920
3921 if (buffer->isMapped())
3922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003923 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003924 return false;
3925 }
3926
3927 // Check for invalid bit combinations
3928 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003930 context->handleError(InvalidOperation()
3931 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003932 return false;
3933 }
3934
3935 GLbitfield writeOnlyBits =
3936 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3937
3938 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003940 context->handleError(InvalidOperation()
3941 << "Invalid access bits when mapping buffer for reading: 0x"
3942 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003943 return false;
3944 }
3945
3946 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003948 context->handleError(
3949 InvalidOperation()
3950 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003951 return false;
3952 }
Geoff Lang79f71042017-08-14 16:43:43 -04003953
3954 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003955}
3956
3957bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003958 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003959 GLintptr offset,
3960 GLsizeiptr length)
3961{
Brandon Jones6cad5662017-06-14 13:25:13 -07003962 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003964 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3965 return false;
3966 }
3967
3968 if (length < 0)
3969 {
3970 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003971 return false;
3972 }
3973
Corentin Walleze4477002017-12-01 14:39:58 -05003974 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003976 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003977 return false;
3978 }
3979
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003980 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003981
3982 if (buffer == nullptr)
3983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003984 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003985 return false;
3986 }
3987
3988 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003990 context->handleError(InvalidOperation()
3991 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003992 return false;
3993 }
3994
3995 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003996 CheckedNumeric<size_t> checkedOffset(offset);
3997 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003998
Jamie Madille2e406c2016-06-02 13:04:10 -04003999 if (!checkedSize.IsValid() ||
4000 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004002 context->handleError(InvalidValue()
4003 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004004 return false;
4005 }
4006
4007 return true;
4008}
4009
Olli Etuaho41997e72016-03-10 13:38:39 +02004010bool ValidateGenOrDelete(Context *context, GLint n)
4011{
4012 if (n < 0)
4013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004014 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004015 return false;
4016 }
4017 return true;
4018}
4019
Jamie Madill5b772312018-03-08 20:28:32 -05004020bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004021{
4022 if (!context->getExtensions().robustClientMemory)
4023 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004024 context->handleError(InvalidOperation()
4025 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004026 return false;
4027 }
4028
4029 if (bufSize < 0)
4030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004031 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004032 return false;
4033 }
4034
4035 return true;
4036}
4037
Jamie Madill5b772312018-03-08 20:28:32 -05004038bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004039{
4040 if (bufSize < numParams)
4041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004042 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4043 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004044 return false;
4045 }
4046
4047 return true;
4048}
4049
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004050bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004051 GLenum target,
4052 GLenum attachment,
4053 GLenum pname,
4054 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004055{
Geoff Lange8afa902017-09-27 15:00:43 -04004056 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004058 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004059 return false;
4060 }
4061
4062 int clientVersion = context->getClientMajorVersion();
4063
4064 switch (pname)
4065 {
4066 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4067 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4068 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4069 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4070 break;
4071
Martin Radeve5285d22017-07-14 16:23:53 +03004072 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4073 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4074 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4075 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4076 if (clientVersion < 3 || !context->getExtensions().multiview)
4077 {
4078 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4079 return false;
4080 }
4081 break;
4082
Geoff Langff5b2d52016-09-07 11:32:23 -04004083 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4084 if (clientVersion < 3 && !context->getExtensions().sRGB)
4085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004086 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004087 return false;
4088 }
4089 break;
4090
4091 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4092 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4093 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4094 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4095 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4096 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4097 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4098 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4099 if (clientVersion < 3)
4100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004101 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004102 return false;
4103 }
4104 break;
4105
Jiawei Shaoa8802472018-05-28 11:17:47 +08004106 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4107 if (!context->getExtensions().geometryShader)
4108 {
4109 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4110 return false;
4111 }
4112 break;
4113
Geoff Langff5b2d52016-09-07 11:32:23 -04004114 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004115 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004116 return false;
4117 }
4118
4119 // Determine if the attachment is a valid enum
4120 switch (attachment)
4121 {
4122 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004123 case GL_DEPTH:
4124 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004125 if (clientVersion < 3)
4126 {
Geoff Langfa125c92017-10-24 13:01:46 -04004127 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004128 return false;
4129 }
4130 break;
4131
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004132 case GL_DEPTH_STENCIL_ATTACHMENT:
4133 if (clientVersion < 3 && !context->isWebGL1())
4134 {
4135 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4136 return false;
4137 }
4138 break;
4139
Geoff Langfa125c92017-10-24 13:01:46 -04004140 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004141 case GL_DEPTH_ATTACHMENT:
4142 case GL_STENCIL_ATTACHMENT:
4143 break;
4144
4145 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004146 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4147 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004148 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4149 {
Geoff Langfa125c92017-10-24 13:01:46 -04004150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004151 return false;
4152 }
4153 break;
4154 }
4155
4156 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4157 ASSERT(framebuffer);
4158
4159 if (framebuffer->id() == 0)
4160 {
4161 if (clientVersion < 3)
4162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004164 return false;
4165 }
4166
4167 switch (attachment)
4168 {
4169 case GL_BACK:
4170 case GL_DEPTH:
4171 case GL_STENCIL:
4172 break;
4173
4174 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004176 return false;
4177 }
4178 }
4179 else
4180 {
4181 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4182 {
4183 // Valid attachment query
4184 }
4185 else
4186 {
4187 switch (attachment)
4188 {
4189 case GL_DEPTH_ATTACHMENT:
4190 case GL_STENCIL_ATTACHMENT:
4191 break;
4192
4193 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004194 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004196 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004197 return false;
4198 }
4199 break;
4200
4201 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004203 return false;
4204 }
4205 }
4206 }
4207
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004208 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004209 if (attachmentObject)
4210 {
4211 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4212 attachmentObject->type() == GL_TEXTURE ||
4213 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4214
4215 switch (pname)
4216 {
4217 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4218 if (attachmentObject->type() != GL_RENDERBUFFER &&
4219 attachmentObject->type() != GL_TEXTURE)
4220 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004222 return false;
4223 }
4224 break;
4225
4226 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4227 if (attachmentObject->type() != GL_TEXTURE)
4228 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004229 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004230 return false;
4231 }
4232 break;
4233
4234 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4235 if (attachmentObject->type() != GL_TEXTURE)
4236 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004237 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004238 return false;
4239 }
4240 break;
4241
4242 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4243 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4244 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004246 return false;
4247 }
4248 break;
4249
4250 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4251 if (attachmentObject->type() != GL_TEXTURE)
4252 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004253 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004254 return false;
4255 }
4256 break;
4257
4258 default:
4259 break;
4260 }
4261 }
4262 else
4263 {
4264 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4265 // is NONE, then querying any other pname will generate INVALID_ENUM.
4266
4267 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4268 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4269 // INVALID_OPERATION for all other pnames
4270
4271 switch (pname)
4272 {
4273 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4274 break;
4275
4276 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4277 if (clientVersion < 3)
4278 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004279 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004280 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004281 return false;
4282 }
4283 break;
4284
4285 default:
4286 if (clientVersion < 3)
4287 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004288 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
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 else
4293 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004294 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004295 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004296 return false;
4297 }
4298 }
4299 }
4300
Martin Radeve5285d22017-07-14 16:23:53 +03004301 if (numParams)
4302 {
4303 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4304 {
4305 // Only when the viewport offsets are queried we can have a varying number of output
4306 // parameters.
4307 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4308 *numParams = numViews * 2;
4309 }
4310 else
4311 {
4312 // For all other queries we can have only one output parameter.
4313 *numParams = 1;
4314 }
4315 }
4316
Geoff Langff5b2d52016-09-07 11:32:23 -04004317 return true;
4318}
4319
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004320bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004321 GLenum target,
4322 GLenum attachment,
4323 GLenum pname,
4324 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004325 GLsizei *length,
4326 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004327{
4328 if (!ValidateRobustEntryPoint(context, bufSize))
4329 {
4330 return false;
4331 }
4332
Brandon Jonesd1049182018-03-28 10:02:20 -07004333 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004334 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004335 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004336 {
4337 return false;
4338 }
4339
Brandon Jonesd1049182018-03-28 10:02:20 -07004340 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004341 {
4342 return false;
4343 }
4344
Brandon Jonesd1049182018-03-28 10:02:20 -07004345 SetRobustLengthParam(length, numParams);
4346
Geoff Langff5b2d52016-09-07 11:32:23 -04004347 return true;
4348}
4349
Jamie Madill5b772312018-03-08 20:28:32 -05004350bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004351 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004352 GLenum pname,
4353 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004354 GLsizei *length,
4355 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004356{
4357 if (!ValidateRobustEntryPoint(context, bufSize))
4358 {
4359 return false;
4360 }
4361
Brandon Jonesd1049182018-03-28 10:02:20 -07004362 GLsizei numParams = 0;
4363
4364 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004365 {
4366 return false;
4367 }
4368
Brandon Jonesd1049182018-03-28 10:02:20 -07004369 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004370 {
4371 return false;
4372 }
4373
Brandon Jonesd1049182018-03-28 10:02:20 -07004374 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004375 return true;
4376}
4377
Jamie Madill5b772312018-03-08 20:28:32 -05004378bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004379 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004380 GLenum pname,
4381 GLsizei bufSize,
4382 GLsizei *length,
4383 GLint64 *params)
4384{
Brandon Jonesd1049182018-03-28 10:02:20 -07004385 GLsizei numParams = 0;
4386
Geoff Langebebe1c2016-10-14 12:01:31 -04004387 if (!ValidateRobustEntryPoint(context, bufSize))
4388 {
4389 return false;
4390 }
4391
Brandon Jonesd1049182018-03-28 10:02:20 -07004392 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004393 {
4394 return false;
4395 }
4396
Brandon Jonesd1049182018-03-28 10:02:20 -07004397 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004398 {
4399 return false;
4400 }
4401
Brandon Jonesd1049182018-03-28 10:02:20 -07004402 SetRobustLengthParam(length, numParams);
4403
Geoff Langff5b2d52016-09-07 11:32:23 -04004404 return true;
4405}
4406
Jamie Madill5b772312018-03-08 20:28:32 -05004407bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004408{
4409 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004410 if (numParams)
4411 {
4412 *numParams = 1;
4413 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004414
4415 Program *programObject = GetValidProgram(context, program);
4416 if (!programObject)
4417 {
4418 return false;
4419 }
4420
4421 switch (pname)
4422 {
4423 case GL_DELETE_STATUS:
4424 case GL_LINK_STATUS:
4425 case GL_VALIDATE_STATUS:
4426 case GL_INFO_LOG_LENGTH:
4427 case GL_ATTACHED_SHADERS:
4428 case GL_ACTIVE_ATTRIBUTES:
4429 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4430 case GL_ACTIVE_UNIFORMS:
4431 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4432 break;
4433
4434 case GL_PROGRAM_BINARY_LENGTH:
4435 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004437 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4438 "requires GL_OES_get_program_binary or "
4439 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004440 return false;
4441 }
4442 break;
4443
4444 case GL_ACTIVE_UNIFORM_BLOCKS:
4445 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4446 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4447 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4448 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4449 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4450 if (context->getClientMajorVersion() < 3)
4451 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004453 return false;
4454 }
4455 break;
4456
Yunchao He61afff12017-03-14 15:34:03 +08004457 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004458 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004459 if (context->getClientVersion() < Version(3, 1))
4460 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004461 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004462 return false;
4463 }
4464 break;
4465
Jiawei Shao6ae51612018-02-23 14:03:25 +08004466 case GL_COMPUTE_WORK_GROUP_SIZE:
4467 if (context->getClientVersion() < Version(3, 1))
4468 {
4469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4470 return false;
4471 }
4472
4473 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4474 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4475 // program which has not been linked successfully, or which does not contain objects to
4476 // form a compute shader.
4477 if (!programObject->isLinked())
4478 {
4479 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4480 return false;
4481 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004482 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004483 {
4484 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4485 return false;
4486 }
4487 break;
4488
Jiawei Shao447bfac2018-03-14 14:23:40 +08004489 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4490 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4491 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4492 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4493 if (!context->getExtensions().geometryShader)
4494 {
4495 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4496 return false;
4497 }
4498
4499 // [EXT_geometry_shader] Chapter 7.12
4500 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4501 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4502 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4503 // successfully, or which does not contain objects to form a geometry shader.
4504 if (!programObject->isLinked())
4505 {
4506 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4507 return false;
4508 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004509 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004510 {
4511 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4512 return false;
4513 }
4514 break;
4515
Geoff Langff5b2d52016-09-07 11:32:23 -04004516 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004517 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004518 return false;
4519 }
4520
4521 return true;
4522}
4523
4524bool ValidateGetProgramivRobustANGLE(Context *context,
4525 GLuint program,
4526 GLenum pname,
4527 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004528 GLsizei *length,
4529 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004530{
4531 if (!ValidateRobustEntryPoint(context, bufSize))
4532 {
4533 return false;
4534 }
4535
Brandon Jonesd1049182018-03-28 10:02:20 -07004536 GLsizei numParams = 0;
4537
4538 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004539 {
4540 return false;
4541 }
4542
Brandon Jonesd1049182018-03-28 10:02:20 -07004543 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004544 {
4545 return false;
4546 }
4547
Brandon Jonesd1049182018-03-28 10:02:20 -07004548 SetRobustLengthParam(length, numParams);
4549
Geoff Langff5b2d52016-09-07 11:32:23 -04004550 return true;
4551}
4552
Geoff Lang740d9022016-10-07 11:20:52 -04004553bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4554 GLenum target,
4555 GLenum pname,
4556 GLsizei bufSize,
4557 GLsizei *length,
4558 GLint *params)
4559{
4560 if (!ValidateRobustEntryPoint(context, bufSize))
4561 {
4562 return false;
4563 }
4564
Brandon Jonesd1049182018-03-28 10:02:20 -07004565 GLsizei numParams = 0;
4566
4567 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004568 {
4569 return false;
4570 }
4571
Brandon Jonesd1049182018-03-28 10:02:20 -07004572 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004573 {
4574 return false;
4575 }
4576
Brandon Jonesd1049182018-03-28 10:02:20 -07004577 SetRobustLengthParam(length, numParams);
4578
Geoff Lang740d9022016-10-07 11:20:52 -04004579 return true;
4580}
4581
Geoff Langd7d0ed32016-10-07 11:33:51 -04004582bool ValidateGetShaderivRobustANGLE(Context *context,
4583 GLuint shader,
4584 GLenum pname,
4585 GLsizei bufSize,
4586 GLsizei *length,
4587 GLint *params)
4588{
4589 if (!ValidateRobustEntryPoint(context, bufSize))
4590 {
4591 return false;
4592 }
4593
Brandon Jonesd1049182018-03-28 10:02:20 -07004594 GLsizei numParams = 0;
4595
4596 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004597 {
4598 return false;
4599 }
4600
Brandon Jonesd1049182018-03-28 10:02:20 -07004601 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004602 {
4603 return false;
4604 }
4605
Brandon Jonesd1049182018-03-28 10:02:20 -07004606 SetRobustLengthParam(length, numParams);
4607
Geoff Langd7d0ed32016-10-07 11:33:51 -04004608 return true;
4609}
4610
Geoff Langc1984ed2016-10-07 12:41:00 -04004611bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004612 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004613 GLenum pname,
4614 GLsizei bufSize,
4615 GLsizei *length,
4616 GLfloat *params)
4617{
4618 if (!ValidateRobustEntryPoint(context, bufSize))
4619 {
4620 return false;
4621 }
4622
Brandon Jonesd1049182018-03-28 10:02:20 -07004623 GLsizei numParams = 0;
4624
4625 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004626 {
4627 return false;
4628 }
4629
Brandon Jonesd1049182018-03-28 10:02:20 -07004630 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004631 {
4632 return false;
4633 }
4634
Brandon Jonesd1049182018-03-28 10:02:20 -07004635 SetRobustLengthParam(length, numParams);
4636
Geoff Langc1984ed2016-10-07 12:41:00 -04004637 return true;
4638}
4639
Geoff Langc1984ed2016-10-07 12:41:00 -04004640bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004641 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004642 GLenum pname,
4643 GLsizei bufSize,
4644 GLsizei *length,
4645 GLint *params)
4646{
Brandon Jonesd1049182018-03-28 10:02:20 -07004647
Geoff Langc1984ed2016-10-07 12:41:00 -04004648 if (!ValidateRobustEntryPoint(context, bufSize))
4649 {
4650 return false;
4651 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004652 GLsizei numParams = 0;
4653 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004654 {
4655 return false;
4656 }
4657
Brandon Jonesd1049182018-03-28 10:02:20 -07004658 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004659 {
4660 return false;
4661 }
4662
Brandon Jonesd1049182018-03-28 10:02:20 -07004663 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004664 return true;
4665}
4666
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004667bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4668 TextureType target,
4669 GLenum pname,
4670 GLsizei bufSize,
4671 GLsizei *length,
4672 GLint *params)
4673{
4674 UNIMPLEMENTED();
4675 return false;
4676}
4677
4678bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4679 TextureType target,
4680 GLenum pname,
4681 GLsizei bufSize,
4682 GLsizei *length,
4683 GLuint *params)
4684{
4685 UNIMPLEMENTED();
4686 return false;
4687}
4688
Geoff Langc1984ed2016-10-07 12:41:00 -04004689bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004690 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004691 GLenum pname,
4692 GLsizei bufSize,
4693 const GLfloat *params)
4694{
4695 if (!ValidateRobustEntryPoint(context, bufSize))
4696 {
4697 return false;
4698 }
4699
4700 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4701}
4702
Geoff Langc1984ed2016-10-07 12:41:00 -04004703bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004704 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004705 GLenum pname,
4706 GLsizei bufSize,
4707 const GLint *params)
4708{
4709 if (!ValidateRobustEntryPoint(context, bufSize))
4710 {
4711 return false;
4712 }
4713
4714 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4715}
4716
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004717bool ValidateTexParameterIivRobustANGLE(Context *context,
4718 TextureType target,
4719 GLenum pname,
4720 GLsizei bufSize,
4721 const GLint *params)
4722{
4723 UNIMPLEMENTED();
4724 return false;
4725}
4726
4727bool ValidateTexParameterIuivRobustANGLE(Context *context,
4728 TextureType target,
4729 GLenum pname,
4730 GLsizei bufSize,
4731 const GLuint *params)
4732{
4733 UNIMPLEMENTED();
4734 return false;
4735}
4736
Geoff Langc1984ed2016-10-07 12:41:00 -04004737bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4738 GLuint sampler,
4739 GLenum pname,
4740 GLuint bufSize,
4741 GLsizei *length,
4742 GLfloat *params)
4743{
4744 if (!ValidateRobustEntryPoint(context, bufSize))
4745 {
4746 return false;
4747 }
4748
Brandon Jonesd1049182018-03-28 10:02:20 -07004749 GLsizei numParams = 0;
4750
4751 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004752 {
4753 return false;
4754 }
4755
Brandon Jonesd1049182018-03-28 10:02:20 -07004756 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004757 {
4758 return false;
4759 }
4760
Brandon Jonesd1049182018-03-28 10:02:20 -07004761 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004762 return true;
4763}
4764
Geoff Langc1984ed2016-10-07 12:41:00 -04004765bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4766 GLuint sampler,
4767 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004768 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004769 GLsizei *length,
4770 GLint *params)
4771{
4772 if (!ValidateRobustEntryPoint(context, bufSize))
4773 {
4774 return false;
4775 }
4776
Brandon Jonesd1049182018-03-28 10:02:20 -07004777 GLsizei numParams = 0;
4778
4779 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004780 {
4781 return false;
4782 }
4783
Brandon Jonesd1049182018-03-28 10:02:20 -07004784 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004785 {
4786 return false;
4787 }
4788
Brandon Jonesd1049182018-03-28 10:02:20 -07004789 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004790 return true;
4791}
4792
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004793bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4794 GLuint sampler,
4795 GLenum pname,
4796 GLsizei bufSize,
4797 GLsizei *length,
4798 GLint *params)
4799{
4800 UNIMPLEMENTED();
4801 return false;
4802}
4803
4804bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4805 GLuint sampler,
4806 GLenum pname,
4807 GLsizei bufSize,
4808 GLsizei *length,
4809 GLuint *params)
4810{
4811 UNIMPLEMENTED();
4812 return false;
4813}
4814
Geoff Langc1984ed2016-10-07 12:41:00 -04004815bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4816 GLuint sampler,
4817 GLenum pname,
4818 GLsizei bufSize,
4819 const GLfloat *params)
4820{
4821 if (!ValidateRobustEntryPoint(context, bufSize))
4822 {
4823 return false;
4824 }
4825
4826 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4827}
4828
Geoff Langc1984ed2016-10-07 12:41:00 -04004829bool ValidateSamplerParameterivRobustANGLE(Context *context,
4830 GLuint sampler,
4831 GLenum pname,
4832 GLsizei bufSize,
4833 const GLint *params)
4834{
4835 if (!ValidateRobustEntryPoint(context, bufSize))
4836 {
4837 return false;
4838 }
4839
4840 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4841}
4842
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004843bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4844 GLuint sampler,
4845 GLenum pname,
4846 GLsizei bufSize,
4847 const GLint *param)
4848{
4849 UNIMPLEMENTED();
4850 return false;
4851}
4852
4853bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4854 GLuint sampler,
4855 GLenum pname,
4856 GLsizei bufSize,
4857 const GLuint *param)
4858{
4859 UNIMPLEMENTED();
4860 return false;
4861}
4862
Geoff Lang0b031062016-10-13 14:30:04 -04004863bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4864 GLuint index,
4865 GLenum pname,
4866 GLsizei bufSize,
4867 GLsizei *length,
4868 GLfloat *params)
4869{
4870 if (!ValidateRobustEntryPoint(context, bufSize))
4871 {
4872 return false;
4873 }
4874
Brandon Jonesd1049182018-03-28 10:02:20 -07004875 GLsizei writeLength = 0;
4876
4877 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004878 {
4879 return false;
4880 }
4881
Brandon Jonesd1049182018-03-28 10:02:20 -07004882 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004883 {
4884 return false;
4885 }
4886
Brandon Jonesd1049182018-03-28 10:02:20 -07004887 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004888 return true;
4889}
4890
Geoff Lang0b031062016-10-13 14:30:04 -04004891bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4892 GLuint index,
4893 GLenum pname,
4894 GLsizei bufSize,
4895 GLsizei *length,
4896 GLint *params)
4897{
4898 if (!ValidateRobustEntryPoint(context, bufSize))
4899 {
4900 return false;
4901 }
4902
Brandon Jonesd1049182018-03-28 10:02:20 -07004903 GLsizei writeLength = 0;
4904
4905 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004906 {
4907 return false;
4908 }
4909
Brandon Jonesd1049182018-03-28 10:02:20 -07004910 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004911 {
4912 return false;
4913 }
4914
Brandon Jonesd1049182018-03-28 10:02:20 -07004915 SetRobustLengthParam(length, writeLength);
4916
Geoff Lang0b031062016-10-13 14:30:04 -04004917 return true;
4918}
4919
Geoff Lang0b031062016-10-13 14:30:04 -04004920bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4921 GLuint index,
4922 GLenum pname,
4923 GLsizei bufSize,
4924 GLsizei *length,
4925 void **pointer)
4926{
4927 if (!ValidateRobustEntryPoint(context, bufSize))
4928 {
4929 return false;
4930 }
4931
Brandon Jonesd1049182018-03-28 10:02:20 -07004932 GLsizei writeLength = 0;
4933
4934 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004935 {
4936 return false;
4937 }
4938
Brandon Jonesd1049182018-03-28 10:02:20 -07004939 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004940 {
4941 return false;
4942 }
4943
Brandon Jonesd1049182018-03-28 10:02:20 -07004944 SetRobustLengthParam(length, writeLength);
4945
Geoff Lang0b031062016-10-13 14:30:04 -04004946 return true;
4947}
4948
Geoff Lang0b031062016-10-13 14:30:04 -04004949bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4950 GLuint index,
4951 GLenum pname,
4952 GLsizei bufSize,
4953 GLsizei *length,
4954 GLint *params)
4955{
4956 if (!ValidateRobustEntryPoint(context, bufSize))
4957 {
4958 return false;
4959 }
4960
Brandon Jonesd1049182018-03-28 10:02:20 -07004961 GLsizei writeLength = 0;
4962
4963 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004964 {
4965 return false;
4966 }
4967
Brandon Jonesd1049182018-03-28 10:02:20 -07004968 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004969 {
4970 return false;
4971 }
4972
Brandon Jonesd1049182018-03-28 10:02:20 -07004973 SetRobustLengthParam(length, writeLength);
4974
Geoff Lang0b031062016-10-13 14:30:04 -04004975 return true;
4976}
4977
Geoff Lang0b031062016-10-13 14:30:04 -04004978bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4979 GLuint index,
4980 GLenum pname,
4981 GLsizei bufSize,
4982 GLsizei *length,
4983 GLuint *params)
4984{
4985 if (!ValidateRobustEntryPoint(context, bufSize))
4986 {
4987 return false;
4988 }
4989
Brandon Jonesd1049182018-03-28 10:02:20 -07004990 GLsizei writeLength = 0;
4991
4992 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004993 {
4994 return false;
4995 }
4996
Brandon Jonesd1049182018-03-28 10:02:20 -07004997 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004998 {
4999 return false;
5000 }
5001
Brandon Jonesd1049182018-03-28 10:02:20 -07005002 SetRobustLengthParam(length, writeLength);
5003
Geoff Lang0b031062016-10-13 14:30:04 -04005004 return true;
5005}
5006
Geoff Lang6899b872016-10-14 11:30:13 -04005007bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5008 GLuint program,
5009 GLuint uniformBlockIndex,
5010 GLenum pname,
5011 GLsizei bufSize,
5012 GLsizei *length,
5013 GLint *params)
5014{
5015 if (!ValidateRobustEntryPoint(context, bufSize))
5016 {
5017 return false;
5018 }
5019
Brandon Jonesd1049182018-03-28 10:02:20 -07005020 GLsizei writeLength = 0;
5021
5022 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5023 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005024 {
5025 return false;
5026 }
5027
Brandon Jonesd1049182018-03-28 10:02:20 -07005028 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005029 {
5030 return false;
5031 }
5032
Brandon Jonesd1049182018-03-28 10:02:20 -07005033 SetRobustLengthParam(length, writeLength);
5034
Geoff Lang6899b872016-10-14 11:30:13 -04005035 return true;
5036}
5037
Brandon Jones416aaf92018-04-10 08:10:16 -07005038bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005039 GLenum target,
5040 GLenum internalformat,
5041 GLenum pname,
5042 GLsizei bufSize,
5043 GLsizei *length,
5044 GLint *params)
5045{
5046 if (!ValidateRobustEntryPoint(context, bufSize))
5047 {
5048 return false;
5049 }
5050
Brandon Jonesd1049182018-03-28 10:02:20 -07005051 GLsizei numParams = 0;
5052
5053 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5054 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005055 {
5056 return false;
5057 }
5058
Brandon Jonesd1049182018-03-28 10:02:20 -07005059 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005060 {
5061 return false;
5062 }
5063
Brandon Jonesd1049182018-03-28 10:02:20 -07005064 SetRobustLengthParam(length, numParams);
5065
Geoff Lang0a9661f2016-10-20 10:59:20 -07005066 return true;
5067}
5068
Jamie Madill5b772312018-03-08 20:28:32 -05005069bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005070 GLuint attribIndex,
5071 GLint size,
5072 GLenum type,
5073 GLboolean pureInteger)
5074{
5075 const Caps &caps = context->getCaps();
5076 if (attribIndex >= caps.maxVertexAttributes)
5077 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005078 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005079 return false;
5080 }
5081
5082 if (size < 1 || size > 4)
5083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005084 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005085 return false;
Shao80957d92017-02-20 21:25:59 +08005086 }
5087
5088 switch (type)
5089 {
5090 case GL_BYTE:
5091 case GL_UNSIGNED_BYTE:
5092 case GL_SHORT:
5093 case GL_UNSIGNED_SHORT:
5094 break;
5095
5096 case GL_INT:
5097 case GL_UNSIGNED_INT:
5098 if (context->getClientMajorVersion() < 3)
5099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005100 context->handleError(InvalidEnum()
5101 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005102 return false;
5103 }
5104 break;
5105
5106 case GL_FIXED:
5107 case GL_FLOAT:
5108 if (pureInteger)
5109 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005110 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005111 return false;
5112 }
5113 break;
5114
5115 case GL_HALF_FLOAT:
5116 if (context->getClientMajorVersion() < 3)
5117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005118 context->handleError(InvalidEnum()
5119 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005120 return false;
5121 }
5122 if (pureInteger)
5123 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005124 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005125 return false;
5126 }
5127 break;
5128
5129 case GL_INT_2_10_10_10_REV:
5130 case GL_UNSIGNED_INT_2_10_10_10_REV:
5131 if (context->getClientMajorVersion() < 3)
5132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005133 context->handleError(InvalidEnum()
5134 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005135 return false;
5136 }
5137 if (pureInteger)
5138 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005140 return false;
5141 }
5142 if (size != 4)
5143 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005144 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5145 "UNSIGNED_INT_2_10_10_10_REV and "
5146 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005147 return false;
5148 }
5149 break;
5150
5151 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005152 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005153 return false;
5154 }
5155
5156 return true;
5157}
5158
Geoff Lang76e65652017-03-27 14:58:02 -04005159// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5160// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5161// specified clear value and the type of a buffer that is being cleared generates an
5162// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005163bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005164 GLint drawbuffer,
5165 const GLenum *validComponentTypes,
5166 size_t validComponentTypeCount)
5167{
5168 const FramebufferAttachment *attachment =
5169 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5170 if (attachment)
5171 {
5172 GLenum componentType = attachment->getFormat().info->componentType;
5173 const GLenum *end = validComponentTypes + validComponentTypeCount;
5174 if (std::find(validComponentTypes, end, componentType) == end)
5175 {
5176 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005177 InvalidOperation()
5178 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005179 return false;
5180 }
5181 }
5182
5183 return true;
5184}
5185
Jamie Madill5b772312018-03-08 20:28:32 -05005186bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005187{
5188 if (!ValidateRobustEntryPoint(context, dataSize))
5189 {
5190 return false;
5191 }
5192
Corentin Wallez336129f2017-10-17 15:55:40 -04005193 gl::Buffer *pixelUnpackBuffer =
5194 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005195 if (pixelUnpackBuffer == nullptr)
5196 {
5197 if (dataSize < imageSize)
5198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005199 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005200 }
5201 }
5202 return true;
5203}
5204
Jamie Madill5b772312018-03-08 20:28:32 -05005205bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005206 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005207 GLenum pname,
5208 bool pointerVersion,
5209 GLsizei *numParams)
5210{
5211 if (numParams)
5212 {
5213 *numParams = 0;
5214 }
5215
Corentin Walleze4477002017-12-01 14:39:58 -05005216 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005218 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005219 return false;
5220 }
5221
5222 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5223 if (!buffer)
5224 {
5225 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005227 return false;
5228 }
5229
5230 const Extensions &extensions = context->getExtensions();
5231
5232 switch (pname)
5233 {
5234 case GL_BUFFER_USAGE:
5235 case GL_BUFFER_SIZE:
5236 break;
5237
5238 case GL_BUFFER_ACCESS_OES:
5239 if (!extensions.mapBuffer)
5240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005241 context->handleError(InvalidEnum()
5242 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005243 return false;
5244 }
5245 break;
5246
5247 case GL_BUFFER_MAPPED:
5248 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5249 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5250 !extensions.mapBufferRange)
5251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005252 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5253 "GL_OES_mapbuffer or "
5254 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005255 return false;
5256 }
5257 break;
5258
5259 case GL_BUFFER_MAP_POINTER:
5260 if (!pointerVersion)
5261 {
5262 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005263 InvalidEnum()
5264 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005265 return false;
5266 }
5267 break;
5268
5269 case GL_BUFFER_ACCESS_FLAGS:
5270 case GL_BUFFER_MAP_OFFSET:
5271 case GL_BUFFER_MAP_LENGTH:
5272 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005274 context->handleError(InvalidEnum()
5275 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005276 return false;
5277 }
5278 break;
5279
5280 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005281 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005282 return false;
5283 }
5284
5285 // All buffer parameter queries return one value.
5286 if (numParams)
5287 {
5288 *numParams = 1;
5289 }
5290
5291 return true;
5292}
5293
5294bool ValidateGetRenderbufferParameterivBase(Context *context,
5295 GLenum target,
5296 GLenum pname,
5297 GLsizei *length)
5298{
5299 if (length)
5300 {
5301 *length = 0;
5302 }
5303
5304 if (target != GL_RENDERBUFFER)
5305 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005306 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005307 return false;
5308 }
5309
5310 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5311 if (renderbuffer == nullptr)
5312 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005314 return false;
5315 }
5316
5317 switch (pname)
5318 {
5319 case GL_RENDERBUFFER_WIDTH:
5320 case GL_RENDERBUFFER_HEIGHT:
5321 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5322 case GL_RENDERBUFFER_RED_SIZE:
5323 case GL_RENDERBUFFER_GREEN_SIZE:
5324 case GL_RENDERBUFFER_BLUE_SIZE:
5325 case GL_RENDERBUFFER_ALPHA_SIZE:
5326 case GL_RENDERBUFFER_DEPTH_SIZE:
5327 case GL_RENDERBUFFER_STENCIL_SIZE:
5328 break;
5329
5330 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5331 if (!context->getExtensions().framebufferMultisample)
5332 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005333 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005334 return false;
5335 }
5336 break;
5337
5338 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005340 return false;
5341 }
5342
5343 if (length)
5344 {
5345 *length = 1;
5346 }
5347 return true;
5348}
5349
5350bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5351{
5352 if (length)
5353 {
5354 *length = 0;
5355 }
5356
5357 if (GetValidShader(context, shader) == nullptr)
5358 {
5359 return false;
5360 }
5361
5362 switch (pname)
5363 {
5364 case GL_SHADER_TYPE:
5365 case GL_DELETE_STATUS:
5366 case GL_COMPILE_STATUS:
5367 case GL_INFO_LOG_LENGTH:
5368 case GL_SHADER_SOURCE_LENGTH:
5369 break;
5370
5371 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5372 if (!context->getExtensions().translatedShaderSource)
5373 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005375 return false;
5376 }
5377 break;
5378
5379 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005380 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005381 return false;
5382 }
5383
5384 if (length)
5385 {
5386 *length = 1;
5387 }
5388 return true;
5389}
5390
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005391bool ValidateGetTexParameterBase(Context *context,
5392 TextureType target,
5393 GLenum pname,
5394 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005395{
5396 if (length)
5397 {
5398 *length = 0;
5399 }
5400
5401 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5402 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005403 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005404 return false;
5405 }
5406
5407 if (context->getTargetTexture(target) == nullptr)
5408 {
5409 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005410 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005411 return false;
5412 }
5413
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005414 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5415 {
5416 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5417 return false;
5418 }
5419
Jamie Madillbe849e42017-05-02 15:49:00 -04005420 switch (pname)
5421 {
5422 case GL_TEXTURE_MAG_FILTER:
5423 case GL_TEXTURE_MIN_FILTER:
5424 case GL_TEXTURE_WRAP_S:
5425 case GL_TEXTURE_WRAP_T:
5426 break;
5427
5428 case GL_TEXTURE_USAGE_ANGLE:
5429 if (!context->getExtensions().textureUsage)
5430 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005431 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005432 return false;
5433 }
5434 break;
5435
5436 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005437 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005438 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005439 return false;
5440 }
5441 break;
5442
5443 case GL_TEXTURE_IMMUTABLE_FORMAT:
5444 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5445 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005446 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005447 return false;
5448 }
5449 break;
5450
5451 case GL_TEXTURE_WRAP_R:
5452 case GL_TEXTURE_IMMUTABLE_LEVELS:
5453 case GL_TEXTURE_SWIZZLE_R:
5454 case GL_TEXTURE_SWIZZLE_G:
5455 case GL_TEXTURE_SWIZZLE_B:
5456 case GL_TEXTURE_SWIZZLE_A:
5457 case GL_TEXTURE_BASE_LEVEL:
5458 case GL_TEXTURE_MAX_LEVEL:
5459 case GL_TEXTURE_MIN_LOD:
5460 case GL_TEXTURE_MAX_LOD:
5461 case GL_TEXTURE_COMPARE_MODE:
5462 case GL_TEXTURE_COMPARE_FUNC:
5463 if (context->getClientMajorVersion() < 3)
5464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005465 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005466 return false;
5467 }
5468 break;
5469
5470 case GL_TEXTURE_SRGB_DECODE_EXT:
5471 if (!context->getExtensions().textureSRGBDecode)
5472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005473 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005474 return false;
5475 }
5476 break;
5477
Yunchao Hebacaa712018-01-30 14:01:39 +08005478 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5479 if (context->getClientVersion() < Version(3, 1))
5480 {
5481 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5482 return false;
5483 }
5484 break;
5485
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005486 case GL_GENERATE_MIPMAP:
5487 case GL_TEXTURE_CROP_RECT_OES:
5488 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5489 // after GL_OES_draw_texture functionality implemented
5490 if (context->getClientMajorVersion() > 1)
5491 {
5492 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5493 return false;
5494 }
5495 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005496 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005497 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005498 return false;
5499 }
5500
5501 if (length)
5502 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005503 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005504 }
5505 return true;
5506}
5507
5508bool ValidateGetVertexAttribBase(Context *context,
5509 GLuint index,
5510 GLenum pname,
5511 GLsizei *length,
5512 bool pointer,
5513 bool pureIntegerEntryPoint)
5514{
5515 if (length)
5516 {
5517 *length = 0;
5518 }
5519
5520 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005522 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005523 return false;
5524 }
5525
5526 if (index >= context->getCaps().maxVertexAttributes)
5527 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005528 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005529 return false;
5530 }
5531
5532 if (pointer)
5533 {
5534 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005536 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005537 return false;
5538 }
5539 }
5540 else
5541 {
5542 switch (pname)
5543 {
5544 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5545 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5546 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5547 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5548 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5549 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5550 case GL_CURRENT_VERTEX_ATTRIB:
5551 break;
5552
5553 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5554 static_assert(
5555 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5556 "ANGLE extension enums not equal to GL enums.");
5557 if (context->getClientMajorVersion() < 3 &&
5558 !context->getExtensions().instancedArrays)
5559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005560 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5561 "requires OpenGL ES 3.0 or "
5562 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005563 return false;
5564 }
5565 break;
5566
5567 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5568 if (context->getClientMajorVersion() < 3)
5569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005570 context->handleError(
5571 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005572 return false;
5573 }
5574 break;
5575
5576 case GL_VERTEX_ATTRIB_BINDING:
5577 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5578 if (context->getClientVersion() < ES_3_1)
5579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005580 context->handleError(InvalidEnum()
5581 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005582 return false;
5583 }
5584 break;
5585
5586 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005587 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005588 return false;
5589 }
5590 }
5591
5592 if (length)
5593 {
5594 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5595 {
5596 *length = 4;
5597 }
5598 else
5599 {
5600 *length = 1;
5601 }
5602 }
5603
5604 return true;
5605}
5606
Jamie Madill4928b7c2017-06-20 12:57:39 -04005607bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005608 GLint x,
5609 GLint y,
5610 GLsizei width,
5611 GLsizei height,
5612 GLenum format,
5613 GLenum type,
5614 GLsizei bufSize,
5615 GLsizei *length,
5616 GLsizei *columns,
5617 GLsizei *rows,
5618 void *pixels)
5619{
5620 if (length != nullptr)
5621 {
5622 *length = 0;
5623 }
5624 if (rows != nullptr)
5625 {
5626 *rows = 0;
5627 }
5628 if (columns != nullptr)
5629 {
5630 *columns = 0;
5631 }
5632
5633 if (width < 0 || height < 0)
5634 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005635 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005636 return false;
5637 }
5638
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005639 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005640
Jamie Madill427064d2018-04-13 16:20:34 -04005641 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005642 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005643 return false;
5644 }
5645
Jamie Madille98b1b52018-03-08 09:47:23 -05005646 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005647 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005648 return false;
5649 }
5650
Jamie Madill690c8eb2018-03-12 15:20:03 -04005651 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005652 ASSERT(framebuffer);
5653
5654 if (framebuffer->getReadBufferState() == GL_NONE)
5655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005657 return false;
5658 }
5659
5660 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5661 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5662 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5663 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5664 // situation is an application error that would lead to a crash in ANGLE.
5665 if (readBuffer == nullptr)
5666 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005668 return false;
5669 }
5670
Martin Radev28031682017-07-28 14:47:56 +03005671 // ANGLE_multiview, Revision 1:
5672 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005673 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5674 // in the current read framebuffer is more than one.
5675 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005676 {
5677 context->handleError(InvalidFramebufferOperation()
5678 << "Attempting to read from a multi-view framebuffer.");
5679 return false;
5680 }
5681
Geoff Lang280ba992017-04-18 16:30:58 -04005682 if (context->getExtensions().webglCompatibility)
5683 {
5684 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5685 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5686 // and type before validating the combination of format and type. However, the
5687 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5688 // verifies that GL_INVALID_OPERATION is generated.
5689 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5690 // dEQP/WebGL.
5691 if (!ValidReadPixelsFormatEnum(context, format))
5692 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005693 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005694 return false;
5695 }
5696
5697 if (!ValidReadPixelsTypeEnum(context, type))
5698 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005699 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005700 return false;
5701 }
5702 }
5703
Jamie Madill690c8eb2018-03-12 15:20:03 -04005704 GLenum currentFormat = GL_NONE;
5705 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5706
5707 GLenum currentType = GL_NONE;
5708 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5709
Jamie Madillbe849e42017-05-02 15:49:00 -04005710 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5711
5712 bool validFormatTypeCombination =
5713 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5714
5715 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5716 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005717 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005718 return false;
5719 }
5720
5721 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005722 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005723 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5724 {
5725 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005726 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005727 return false;
5728 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005729 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5730 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5731 {
5732 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5733 return false;
5734 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005735
5736 // .. the data would be packed to the buffer object such that the memory writes required
5737 // would exceed the data store size.
5738 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5739 const gl::Extents size(width, height, 1);
5740 const auto &pack = context->getGLState().getPackState();
5741
Jamie Madillca2ff382018-07-11 09:01:17 -04005742 GLuint endByte = 0;
5743 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005744 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005745 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005746 return false;
5747 }
5748
Jamie Madillbe849e42017-05-02 15:49:00 -04005749 if (bufSize >= 0)
5750 {
5751 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5752 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005754 return false;
5755 }
5756 }
5757
5758 if (pixelPackBuffer != nullptr)
5759 {
5760 CheckedNumeric<size_t> checkedEndByte(endByte);
5761 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5762 checkedEndByte += checkedOffset;
5763
5764 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5765 {
5766 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005767 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005768 return false;
5769 }
5770 }
5771
5772 if (pixelPackBuffer == nullptr && length != nullptr)
5773 {
5774 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5775 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005776 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005777 return false;
5778 }
5779
5780 *length = static_cast<GLsizei>(endByte);
5781 }
5782
Geoff Langa953b522018-02-21 16:56:23 -05005783 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 angle::CheckedNumeric<int> clippedExtent(length);
5785 if (start < 0)
5786 {
5787 // "subtract" the area that is less than 0
5788 clippedExtent += start;
5789 }
5790
Geoff Langa953b522018-02-21 16:56:23 -05005791 angle::CheckedNumeric<int> readExtent = start;
5792 readExtent += length;
5793 if (!readExtent.IsValid())
5794 {
5795 return false;
5796 }
5797
5798 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005799 {
5800 // Subtract the region to the right of the read buffer
5801 clippedExtent -= (readExtent - bufferSize);
5802 }
5803
5804 if (!clippedExtent.IsValid())
5805 {
Geoff Langa953b522018-02-21 16:56:23 -05005806 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 }
5808
Geoff Langa953b522018-02-21 16:56:23 -05005809 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5810 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005811 };
5812
Geoff Langa953b522018-02-21 16:56:23 -05005813 GLsizei writtenColumns = 0;
5814 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5815 {
5816 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5817 return false;
5818 }
5819
5820 GLsizei writtenRows = 0;
5821 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5822 {
5823 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5824 return false;
5825 }
5826
Jamie Madillbe849e42017-05-02 15:49:00 -04005827 if (columns != nullptr)
5828 {
Geoff Langa953b522018-02-21 16:56:23 -05005829 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005830 }
5831
5832 if (rows != nullptr)
5833 {
Geoff Langa953b522018-02-21 16:56:23 -05005834 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005835 }
5836
5837 return true;
5838}
5839
5840template <typename ParamType>
5841bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005842 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005843 GLenum pname,
5844 GLsizei bufSize,
5845 const ParamType *params)
5846{
5847 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5848 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005849 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005850 return false;
5851 }
5852
5853 if (context->getTargetTexture(target) == nullptr)
5854 {
5855 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005856 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005857 return false;
5858 }
5859
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005860 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005861 if (bufSize >= 0 && bufSize < minBufSize)
5862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005864 return false;
5865 }
5866
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005867 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5868 {
5869 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5870 return false;
5871 }
5872
Jamie Madillbe849e42017-05-02 15:49:00 -04005873 switch (pname)
5874 {
5875 case GL_TEXTURE_WRAP_R:
5876 case GL_TEXTURE_SWIZZLE_R:
5877 case GL_TEXTURE_SWIZZLE_G:
5878 case GL_TEXTURE_SWIZZLE_B:
5879 case GL_TEXTURE_SWIZZLE_A:
5880 case GL_TEXTURE_BASE_LEVEL:
5881 case GL_TEXTURE_MAX_LEVEL:
5882 case GL_TEXTURE_COMPARE_MODE:
5883 case GL_TEXTURE_COMPARE_FUNC:
5884 case GL_TEXTURE_MIN_LOD:
5885 case GL_TEXTURE_MAX_LOD:
5886 if (context->getClientMajorVersion() < 3)
5887 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005888 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005889 return false;
5890 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005891 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005893 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5894 "available without "
5895 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005896 return false;
5897 }
5898 break;
5899
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005900 case GL_GENERATE_MIPMAP:
5901 case GL_TEXTURE_CROP_RECT_OES:
5902 if (context->getClientMajorVersion() > 1)
5903 {
5904 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5905 return false;
5906 }
5907 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005908 default:
5909 break;
5910 }
5911
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005912 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005913 {
5914 switch (pname)
5915 {
5916 case GL_TEXTURE_MIN_FILTER:
5917 case GL_TEXTURE_MAG_FILTER:
5918 case GL_TEXTURE_WRAP_S:
5919 case GL_TEXTURE_WRAP_T:
5920 case GL_TEXTURE_WRAP_R:
5921 case GL_TEXTURE_MIN_LOD:
5922 case GL_TEXTURE_MAX_LOD:
5923 case GL_TEXTURE_COMPARE_MODE:
5924 case GL_TEXTURE_COMPARE_FUNC:
5925 context->handleError(InvalidEnum()
5926 << "Invalid parameter for 2D multisampled textures.");
5927 return false;
5928 }
5929 }
5930
Jamie Madillbe849e42017-05-02 15:49:00 -04005931 switch (pname)
5932 {
5933 case GL_TEXTURE_WRAP_S:
5934 case GL_TEXTURE_WRAP_T:
5935 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005936 {
5937 bool restrictedWrapModes =
5938 target == TextureType::External || target == TextureType::Rectangle;
5939 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005940 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005941 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005942 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005943 }
5944 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005945
5946 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005947 {
5948 bool restrictedMinFilter =
5949 target == TextureType::External || target == TextureType::Rectangle;
5950 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005951 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005952 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005953 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005954 }
5955 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005956
5957 case GL_TEXTURE_MAG_FILTER:
5958 if (!ValidateTextureMagFilterValue(context, params))
5959 {
5960 return false;
5961 }
5962 break;
5963
5964 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005965 if (!context->getExtensions().textureUsage)
5966 {
5967 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5968 return false;
5969 }
5970
Jamie Madillbe849e42017-05-02 15:49:00 -04005971 switch (ConvertToGLenum(params[0]))
5972 {
5973 case GL_NONE:
5974 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5975 break;
5976
5977 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005978 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005979 return false;
5980 }
5981 break;
5982
5983 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005984 {
5985 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5986 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005987 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005988 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005989 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005990 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5991 }
5992 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005993
5994 case GL_TEXTURE_MIN_LOD:
5995 case GL_TEXTURE_MAX_LOD:
5996 // any value is permissible
5997 break;
5998
5999 case GL_TEXTURE_COMPARE_MODE:
6000 if (!ValidateTextureCompareModeValue(context, params))
6001 {
6002 return false;
6003 }
6004 break;
6005
6006 case GL_TEXTURE_COMPARE_FUNC:
6007 if (!ValidateTextureCompareFuncValue(context, params))
6008 {
6009 return false;
6010 }
6011 break;
6012
6013 case GL_TEXTURE_SWIZZLE_R:
6014 case GL_TEXTURE_SWIZZLE_G:
6015 case GL_TEXTURE_SWIZZLE_B:
6016 case GL_TEXTURE_SWIZZLE_A:
6017 switch (ConvertToGLenum(params[0]))
6018 {
6019 case GL_RED:
6020 case GL_GREEN:
6021 case GL_BLUE:
6022 case GL_ALPHA:
6023 case GL_ZERO:
6024 case GL_ONE:
6025 break;
6026
6027 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006028 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006029 return false;
6030 }
6031 break;
6032
6033 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006034 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006036 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006037 return false;
6038 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006039 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006041 context->handleError(InvalidOperation()
6042 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006043 return false;
6044 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006045 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006046 {
6047 context->handleError(InvalidOperation()
6048 << "Base level must be 0 for multisampled textures.");
6049 return false;
6050 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006051 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006052 {
6053 context->handleError(InvalidOperation()
6054 << "Base level must be 0 for rectangle textures.");
6055 return false;
6056 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006057 break;
6058
6059 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006060 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006062 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006063 return false;
6064 }
6065 break;
6066
6067 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6068 if (context->getClientVersion() < Version(3, 1))
6069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006070 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006071 return false;
6072 }
6073 switch (ConvertToGLenum(params[0]))
6074 {
6075 case GL_DEPTH_COMPONENT:
6076 case GL_STENCIL_INDEX:
6077 break;
6078
6079 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006080 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006081 return false;
6082 }
6083 break;
6084
6085 case GL_TEXTURE_SRGB_DECODE_EXT:
6086 if (!ValidateTextureSRGBDecodeValue(context, params))
6087 {
6088 return false;
6089 }
6090 break;
6091
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006092 case GL_GENERATE_MIPMAP:
6093 case GL_TEXTURE_CROP_RECT_OES:
6094 if (context->getClientMajorVersion() > 1)
6095 {
6096 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6097 return false;
6098 }
6099 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006100 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006101 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006102 return false;
6103 }
6104
6105 return true;
6106}
6107
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006108template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6109template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006110
Jamie Madill5b772312018-03-08 20:28:32 -05006111bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006112{
6113 if (index >= MAX_VERTEX_ATTRIBS)
6114 {
6115 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6116 return false;
6117 }
6118
6119 return true;
6120}
6121
6122bool ValidateGetActiveUniformBlockivBase(Context *context,
6123 GLuint program,
6124 GLuint uniformBlockIndex,
6125 GLenum pname,
6126 GLsizei *length)
6127{
6128 if (length)
6129 {
6130 *length = 0;
6131 }
6132
6133 if (context->getClientMajorVersion() < 3)
6134 {
6135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6136 return false;
6137 }
6138
6139 Program *programObject = GetValidProgram(context, program);
6140 if (!programObject)
6141 {
6142 return false;
6143 }
6144
6145 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6146 {
6147 context->handleError(InvalidValue()
6148 << "uniformBlockIndex exceeds active uniform block count.");
6149 return false;
6150 }
6151
6152 switch (pname)
6153 {
6154 case GL_UNIFORM_BLOCK_BINDING:
6155 case GL_UNIFORM_BLOCK_DATA_SIZE:
6156 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6157 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6158 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6159 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6160 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6161 break;
6162
6163 default:
6164 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6165 return false;
6166 }
6167
6168 if (length)
6169 {
6170 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6171 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006172 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006173 programObject->getUniformBlockByIndex(uniformBlockIndex);
6174 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6175 }
6176 else
6177 {
6178 *length = 1;
6179 }
6180 }
6181
6182 return true;
6183}
6184
Jamie Madill9696d072017-08-26 23:19:57 -04006185template <typename ParamType>
6186bool ValidateSamplerParameterBase(Context *context,
6187 GLuint sampler,
6188 GLenum pname,
6189 GLsizei bufSize,
6190 ParamType *params)
6191{
6192 if (context->getClientMajorVersion() < 3)
6193 {
6194 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6195 return false;
6196 }
6197
6198 if (!context->isSampler(sampler))
6199 {
6200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6201 return false;
6202 }
6203
6204 const GLsizei minBufSize = 1;
6205 if (bufSize >= 0 && bufSize < minBufSize)
6206 {
6207 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6208 return false;
6209 }
6210
6211 switch (pname)
6212 {
6213 case GL_TEXTURE_WRAP_S:
6214 case GL_TEXTURE_WRAP_T:
6215 case GL_TEXTURE_WRAP_R:
6216 if (!ValidateTextureWrapModeValue(context, params, false))
6217 {
6218 return false;
6219 }
6220 break;
6221
6222 case GL_TEXTURE_MIN_FILTER:
6223 if (!ValidateTextureMinFilterValue(context, params, false))
6224 {
6225 return false;
6226 }
6227 break;
6228
6229 case GL_TEXTURE_MAG_FILTER:
6230 if (!ValidateTextureMagFilterValue(context, params))
6231 {
6232 return false;
6233 }
6234 break;
6235
6236 case GL_TEXTURE_MIN_LOD:
6237 case GL_TEXTURE_MAX_LOD:
6238 // any value is permissible
6239 break;
6240
6241 case GL_TEXTURE_COMPARE_MODE:
6242 if (!ValidateTextureCompareModeValue(context, params))
6243 {
6244 return false;
6245 }
6246 break;
6247
6248 case GL_TEXTURE_COMPARE_FUNC:
6249 if (!ValidateTextureCompareFuncValue(context, params))
6250 {
6251 return false;
6252 }
6253 break;
6254
6255 case GL_TEXTURE_SRGB_DECODE_EXT:
6256 if (!ValidateTextureSRGBDecodeValue(context, params))
6257 {
6258 return false;
6259 }
6260 break;
6261
Luc Ferron1b1a8642018-01-23 15:12:01 -05006262 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6263 {
6264 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6265 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6266 {
6267 return false;
6268 }
6269 }
6270 break;
6271
Jamie Madill9696d072017-08-26 23:19:57 -04006272 default:
6273 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6274 return false;
6275 }
6276
6277 return true;
6278}
6279
6280template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6281template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6282
6283bool ValidateGetSamplerParameterBase(Context *context,
6284 GLuint sampler,
6285 GLenum pname,
6286 GLsizei *length)
6287{
6288 if (length)
6289 {
6290 *length = 0;
6291 }
6292
6293 if (context->getClientMajorVersion() < 3)
6294 {
6295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6296 return false;
6297 }
6298
6299 if (!context->isSampler(sampler))
6300 {
6301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6302 return false;
6303 }
6304
6305 switch (pname)
6306 {
6307 case GL_TEXTURE_WRAP_S:
6308 case GL_TEXTURE_WRAP_T:
6309 case GL_TEXTURE_WRAP_R:
6310 case GL_TEXTURE_MIN_FILTER:
6311 case GL_TEXTURE_MAG_FILTER:
6312 case GL_TEXTURE_MIN_LOD:
6313 case GL_TEXTURE_MAX_LOD:
6314 case GL_TEXTURE_COMPARE_MODE:
6315 case GL_TEXTURE_COMPARE_FUNC:
6316 break;
6317
Luc Ferron1b1a8642018-01-23 15:12:01 -05006318 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6319 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6320 {
6321 return false;
6322 }
6323 break;
6324
Jamie Madill9696d072017-08-26 23:19:57 -04006325 case GL_TEXTURE_SRGB_DECODE_EXT:
6326 if (!context->getExtensions().textureSRGBDecode)
6327 {
6328 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6329 return false;
6330 }
6331 break;
6332
6333 default:
6334 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6335 return false;
6336 }
6337
6338 if (length)
6339 {
6340 *length = 1;
6341 }
6342 return true;
6343}
6344
6345bool ValidateGetInternalFormativBase(Context *context,
6346 GLenum target,
6347 GLenum internalformat,
6348 GLenum pname,
6349 GLsizei bufSize,
6350 GLsizei *numParams)
6351{
6352 if (numParams)
6353 {
6354 *numParams = 0;
6355 }
6356
6357 if (context->getClientMajorVersion() < 3)
6358 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006359 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006360 return false;
6361 }
6362
6363 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006364 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006365 {
6366 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6367 return false;
6368 }
6369
6370 switch (target)
6371 {
6372 case GL_RENDERBUFFER:
6373 break;
6374
6375 case GL_TEXTURE_2D_MULTISAMPLE:
6376 if (context->getClientVersion() < ES_3_1)
6377 {
6378 context->handleError(InvalidOperation()
6379 << "Texture target requires at least OpenGL ES 3.1.");
6380 return false;
6381 }
6382 break;
6383
6384 default:
6385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6386 return false;
6387 }
6388
6389 if (bufSize < 0)
6390 {
6391 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6392 return false;
6393 }
6394
6395 GLsizei maxWriteParams = 0;
6396 switch (pname)
6397 {
6398 case GL_NUM_SAMPLE_COUNTS:
6399 maxWriteParams = 1;
6400 break;
6401
6402 case GL_SAMPLES:
6403 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6404 break;
6405
6406 default:
6407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6408 return false;
6409 }
6410
6411 if (numParams)
6412 {
6413 // glGetInternalFormativ will not overflow bufSize
6414 *numParams = std::min(bufSize, maxWriteParams);
6415 }
6416
6417 return true;
6418}
6419
Jamie Madille98b1b52018-03-08 09:47:23 -05006420bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6421{
Jamie Madill427064d2018-04-13 16:20:34 -04006422 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006423 {
6424 context->handleError(InvalidOperation());
6425 return false;
6426 }
6427 return true;
6428}
6429
Lingfeng Yang038dd532018-03-29 17:31:52 -07006430bool ValidateMultitextureUnit(Context *context, GLenum texture)
6431{
6432 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6433 {
6434 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6435 return false;
6436 }
6437 return true;
6438}
6439
Jamie Madillc29968b2016-01-20 11:17:23 -05006440} // namespace gl