blob: a014ac31396b782f0cca92f2851be2c98ea5eb6d [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 Madilldfde6ab2016-06-09 07:07:18 -0700112 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -0400113 const gl::Program *program = state.getProgram();
114
Jamie Madillac43aaa2018-07-31 11:22:13 -0400115 if (!ValidateDrawClientAttribs(context))
Jamie Madill51af38b2018-04-15 08:50:56 -0400116 {
Jamie Madillac43aaa2018-07-31 11:22:13 -0400117 return false;
Jamie Madill51af38b2018-04-15 08:50:56 -0400118 }
119
120 // If we're drawing zero vertices, we have enough data.
121 if (vertexCount <= 0 || primcount <= 0)
122 {
123 return true;
124 }
125
Jamie Madillac43aaa2018-07-31 11:22:13 -0400126 const VertexArray *vao = state.getVertexArray();
Jamie Madill231c7f52017-04-26 13:45:37 -0400127 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800128 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill51af38b2018-04-15 08:50:56 -0400129
Jamie Madilldc358af2018-07-31 11:22:13 -0400130 const AttributesMask &activeAttribs = context->getStateCache().getActiveBufferedAttribsMask();
Jamie Madill51af38b2018-04-15 08:50:56 -0400131
132 for (size_t attributeIndex : activeAttribs)
Jamie Madill1ca74672015-07-21 15:14:11 -0400133 {
134 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400135 ASSERT(attrib.enabled);
Corentin Wallez672f7f32017-06-15 17:42:17 -0400136
Lingfeng Yang038dd532018-03-29 17:31:52 -0700137 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Jamie Madill2eb65032018-07-30 10:25:57 -0400138 ASSERT(context->isGLES1() || program->isAttribLocationActive(attributeIndex));
Corentin Wallezfd456442016-12-21 17:57:00 -0500139
Jamie Madillbdc610a2018-07-30 10:26:00 -0400140 GLint maxVertexElement = binding.getDivisor() != 0 ? (primcount - 1) : maxVertex;
141
142 if (maxVertexElement > attrib.getCachedElementLimit())
Corentin Wallezfd456442016-12-21 17:57:00 -0500143 {
Jamie Madillbdc610a2018-07-30 10:26:00 -0400144 // An overflow can happen when adding the offset. Negative indicates overflow.
145 if (attrib.getCachedElementLimit() < 0)
146 {
147 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
148 return false;
149 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500150
Jamie Madillbdc610a2018-07-30 10:26:00 -0400151 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
152 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
Brandon Jonesafa75152017-07-21 13:11:29 -0700153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500154 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400155 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400156 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800157
Jamie Madill1ca74672015-07-21 15:14:11 -0400158 return true;
159}
160
Jamie Madill5b772312018-03-08 20:28:32 -0500161bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400162{
163 switch (type)
164 {
165 // Types referenced in Table 3.4 of the ES 2.0.25 spec
166 case GL_UNSIGNED_BYTE:
167 case GL_UNSIGNED_SHORT_4_4_4_4:
168 case GL_UNSIGNED_SHORT_5_5_5_1:
169 case GL_UNSIGNED_SHORT_5_6_5:
170 return context->getClientVersion() >= ES_2_0;
171
172 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
173 case GL_BYTE:
174 case GL_INT:
175 case GL_SHORT:
176 case GL_UNSIGNED_INT:
177 case GL_UNSIGNED_INT_10F_11F_11F_REV:
178 case GL_UNSIGNED_INT_24_8:
179 case GL_UNSIGNED_INT_2_10_10_10_REV:
180 case GL_UNSIGNED_INT_5_9_9_9_REV:
181 case GL_UNSIGNED_SHORT:
182 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
183 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
184 return context->getClientVersion() >= ES_3_0;
185
186 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400187 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
188 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400189
190 case GL_HALF_FLOAT:
191 return context->getClientVersion() >= ES_3_0 ||
192 context->getExtensions().textureHalfFloat;
193
194 case GL_HALF_FLOAT_OES:
195 return context->getExtensions().colorBufferHalfFloat;
196
197 default:
198 return false;
199 }
200}
201
Jamie Madill5b772312018-03-08 20:28:32 -0500202bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400203{
204 switch (format)
205 {
206 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
207 case GL_RGBA:
208 case GL_RGB:
209 case GL_ALPHA:
210 return context->getClientVersion() >= ES_2_0;
211
212 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
213 case GL_RG:
214 case GL_RED:
215 case GL_RGBA_INTEGER:
216 case GL_RGB_INTEGER:
217 case GL_RG_INTEGER:
218 case GL_RED_INTEGER:
219 return context->getClientVersion() >= ES_3_0;
220
221 case GL_SRGB_ALPHA_EXT:
222 case GL_SRGB_EXT:
223 return context->getExtensions().sRGB;
224
225 case GL_BGRA_EXT:
226 return context->getExtensions().readFormatBGRA;
227
228 default:
229 return false;
230 }
231}
232
Jamie Madill5b772312018-03-08 20:28:32 -0500233bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400234 GLenum framebufferComponentType,
235 GLenum format,
236 GLenum type)
237{
238 switch (framebufferComponentType)
239 {
240 case GL_UNSIGNED_NORMALIZED:
241 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
242 // ReadPixels with BGRA even if the extension is not present
243 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
244 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
245 type == GL_UNSIGNED_BYTE);
246
247 case GL_SIGNED_NORMALIZED:
248 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
249
250 case GL_INT:
251 return (format == GL_RGBA_INTEGER && type == GL_INT);
252
253 case GL_UNSIGNED_INT:
254 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
255
256 case GL_FLOAT:
257 return (format == GL_RGBA && type == GL_FLOAT);
258
259 default:
260 UNREACHABLE();
261 return false;
262 }
263}
264
Geoff Langc1984ed2016-10-07 12:41:00 -0400265template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400266bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400267{
268 switch (ConvertToGLenum(params[0]))
269 {
270 case GL_CLAMP_TO_EDGE:
271 break;
272
273 case GL_REPEAT:
274 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400275 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400276 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400277 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400279 return false;
280 }
281 break;
282
283 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700284 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400285 return false;
286 }
287
288 return true;
289}
290
291template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400292bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400293{
294 switch (ConvertToGLenum(params[0]))
295 {
296 case GL_NEAREST:
297 case GL_LINEAR:
298 break;
299
300 case GL_NEAREST_MIPMAP_NEAREST:
301 case GL_LINEAR_MIPMAP_NEAREST:
302 case GL_NEAREST_MIPMAP_LINEAR:
303 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400304 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 {
306 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400308 return false;
309 }
310 break;
311
312 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700313 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400314 return false;
315 }
316
317 return true;
318}
319
320template <typename ParamType>
321bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
322{
323 switch (ConvertToGLenum(params[0]))
324 {
325 case GL_NEAREST:
326 case GL_LINEAR:
327 break;
328
329 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700330 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400331 return false;
332 }
333
334 return true;
335}
336
337template <typename ParamType>
338bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
339{
340 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
341 switch (ConvertToGLenum(params[0]))
342 {
343 case GL_NONE:
344 case GL_COMPARE_REF_TO_TEXTURE:
345 break;
346
347 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700348 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400349 return false;
350 }
351
352 return true;
353}
354
355template <typename ParamType>
356bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
357{
358 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
359 switch (ConvertToGLenum(params[0]))
360 {
361 case GL_LEQUAL:
362 case GL_GEQUAL:
363 case GL_LESS:
364 case GL_GREATER:
365 case GL_EQUAL:
366 case GL_NOTEQUAL:
367 case GL_ALWAYS:
368 case GL_NEVER:
369 break;
370
371 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700372 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400373 return false;
374 }
375
376 return true;
377}
378
379template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700380bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
381{
382 if (!context->getExtensions().textureSRGBDecode)
383 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700384 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700385 return false;
386 }
387
388 switch (ConvertToGLenum(params[0]))
389 {
390 case GL_DECODE_EXT:
391 case GL_SKIP_DECODE_EXT:
392 break;
393
394 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700395 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700396 return false;
397 }
398
399 return true;
400}
401
Luc Ferron1b1a8642018-01-23 15:12:01 -0500402bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
403{
404 if (!context->getExtensions().textureFilterAnisotropic)
405 {
406 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
407 return false;
408 }
409
410 return true;
411}
412
413bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
414{
415 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
416 {
417 return false;
418 }
419
420 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
421
422 if (paramValue < 1 || paramValue > largest)
423 {
424 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
425 return false;
426 }
427
428 return true;
429}
430
Jamie Madill5b772312018-03-08 20:28:32 -0500431bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400432{
433 const Program *program = context->getGLState().getProgram();
434 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
435
Brandon Jonesc405ae72017-12-06 14:15:03 -0800436 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
437 framebuffer->getDrawBufferTypeMask().to_ulong(),
438 program->getActiveOutputVariables().to_ulong(),
439 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400440 {
Brandon Jones76746f92017-11-22 11:44:41 -0800441 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
442 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400443 }
444
445 return true;
446}
447
Jamie Madill5b772312018-03-08 20:28:32 -0500448bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400449{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700450 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400451 const Program *program = context->getGLState().getProgram();
452 const VertexArray *vao = context->getGLState().getVertexArray();
453
Brandon Jonesc405ae72017-12-06 14:15:03 -0800454 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
455 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
456 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
457
458 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
459 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
460 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
461
462 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
463 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400464 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
466 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400467 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400468 return true;
469}
470
Jamie Madill493f9572018-05-24 19:52:15 -0400471bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
472 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800473{
474 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400475 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800476 {
Jamie Madill493f9572018-05-24 19:52:15 -0400477 case PrimitiveMode::Points:
478 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
479 case PrimitiveMode::Lines:
480 case PrimitiveMode::LineStrip:
481 case PrimitiveMode::LineLoop:
482 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
483 case PrimitiveMode::LinesAdjacency:
484 case PrimitiveMode::LineStripAdjacency:
485 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
486 case PrimitiveMode::Triangles:
487 case PrimitiveMode::TriangleFan:
488 case PrimitiveMode::TriangleStrip:
489 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
490 case PrimitiveMode::TrianglesAdjacency:
491 case PrimitiveMode::TriangleStripAdjacency:
492 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800493 default:
494 UNREACHABLE();
495 return false;
496 }
497}
498
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700499// GLES1 texture parameters are a small subset of the others
500bool IsValidGLES1TextureParameter(GLenum pname)
501{
502 switch (pname)
503 {
504 case GL_TEXTURE_MAG_FILTER:
505 case GL_TEXTURE_MIN_FILTER:
506 case GL_TEXTURE_WRAP_S:
507 case GL_TEXTURE_WRAP_T:
508 case GL_TEXTURE_WRAP_R:
509 case GL_GENERATE_MIPMAP:
510 case GL_TEXTURE_CROP_RECT_OES:
511 return true;
512 default:
513 return false;
514 }
515}
516
Geoff Langf41a7152016-09-19 15:11:17 -0400517} // anonymous namespace
518
Brandon Jonesd1049182018-03-28 10:02:20 -0700519void SetRobustLengthParam(GLsizei *length, GLsizei value)
520{
521 if (length)
522 {
523 *length = value;
524 }
525}
526
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500527bool IsETC2EACFormat(const GLenum format)
528{
529 // ES 3.1, Table 8.19
530 switch (format)
531 {
532 case GL_COMPRESSED_R11_EAC:
533 case GL_COMPRESSED_SIGNED_R11_EAC:
534 case GL_COMPRESSED_RG11_EAC:
535 case GL_COMPRESSED_SIGNED_RG11_EAC:
536 case GL_COMPRESSED_RGB8_ETC2:
537 case GL_COMPRESSED_SRGB8_ETC2:
538 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
539 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
540 case GL_COMPRESSED_RGBA8_ETC2_EAC:
541 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
542 return true;
543
544 default:
545 return false;
546 }
547}
548
Jamie Madill5b772312018-03-08 20:28:32 -0500549bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400550{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800551 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400552 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800553 case TextureType::_2D:
554 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800555 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400556
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800557 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400558 return context->getExtensions().textureRectangle;
559
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800560 case TextureType::_3D:
561 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800562 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500563
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800564 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800565 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400566
He Yunchaoced53ae2016-11-29 15:00:51 +0800567 default:
568 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500569 }
Jamie Madill35d15012013-10-07 10:46:37 -0400570}
571
Jamie Madill5b772312018-03-08 20:28:32 -0500572bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500573{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800574 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500575 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800576 case TextureType::_2D:
577 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500578 return true;
579
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800580 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400581 return context->getExtensions().textureRectangle;
582
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500583 default:
584 return false;
585 }
586}
587
Jamie Madill5b772312018-03-08 20:28:32 -0500588bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500589{
590 switch (target)
591 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800592 case TextureType::_3D:
593 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300594 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500595
596 default:
597 return false;
598 }
599}
600
Ian Ewellbda75592016-04-18 17:25:54 -0400601// Most texture GL calls are not compatible with external textures, so we have a separate validation
602// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500603bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400604{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800605 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400606 (context->getExtensions().eglImageExternal ||
607 context->getExtensions().eglStreamConsumerExternal);
608}
609
Shannon Woods4dfed832014-03-17 20:03:39 -0400610// This function differs from ValidTextureTarget in that the target must be
611// usable as the destination of a 2D operation-- so a cube face is valid, but
612// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400613// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500614bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400615{
616 switch (target)
617 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800618 case TextureTarget::_2D:
619 case TextureTarget::CubeMapNegativeX:
620 case TextureTarget::CubeMapNegativeY:
621 case TextureTarget::CubeMapNegativeZ:
622 case TextureTarget::CubeMapPositiveX:
623 case TextureTarget::CubeMapPositiveY:
624 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800625 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800626 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400627 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800628 default:
629 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500630 }
631}
632
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800633bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400634 PrimitiveMode transformFeedbackPrimitiveMode,
635 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800636{
637 ASSERT(context);
638
639 if (!context->getExtensions().geometryShader)
640 {
641 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
642 // that does not match the current transform feedback object's draw mode (if transform
643 // feedback is active), (3.0.2, section 2.14, pg 86)
644 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
645 }
646
647 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400648 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800649 {
Jamie Madill493f9572018-05-24 19:52:15 -0400650 case PrimitiveMode::Points:
651 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
652 case PrimitiveMode::Lines:
653 case PrimitiveMode::LineStrip:
654 case PrimitiveMode::LineLoop:
655 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
656 case PrimitiveMode::Triangles:
657 case PrimitiveMode::TriangleFan:
658 case PrimitiveMode::TriangleStrip:
659 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800660 default:
661 UNREACHABLE();
662 return false;
663 }
664}
665
Jamie Madill5b772312018-03-08 20:28:32 -0500666bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400667 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400668 GLsizei count,
669 GLenum type,
670 const GLvoid *indices,
671 GLsizei primcount)
672{
673 if (primcount < 0)
674 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700675 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400676 return false;
677 }
678
679 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
680 {
681 return false;
682 }
683
Jamie Madill9fdaa492018-02-16 10:52:11 -0500684 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400685}
686
687bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400688 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400689 GLint first,
690 GLsizei count,
691 GLsizei primcount)
692{
693 if (primcount < 0)
694 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700695 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400696 return false;
697 }
698
699 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
700 {
701 return false;
702 }
703
Jamie Madill9fdaa492018-02-16 10:52:11 -0500704 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400705}
706
Jamie Madill5b772312018-03-08 20:28:32 -0500707bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400708{
709 // Verify there is at least one active attribute with a divisor of zero
710 const State &state = context->getGLState();
711
712 Program *program = state.getProgram();
713
714 const auto &attribs = state.getVertexArray()->getVertexAttributes();
715 const auto &bindings = state.getVertexArray()->getVertexBindings();
716 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
717 {
718 const VertexAttribute &attrib = attribs[attributeIndex];
719 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300720 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400721 {
722 return true;
723 }
724 }
725
Brandon Jonesafa75152017-07-21 13:11:29 -0700726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400727 return false;
728}
729
Jamie Madill5b772312018-03-08 20:28:32 -0500730bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500731{
732 switch (target)
733 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800734 case TextureType::_3D:
735 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 return true;
737 default:
738 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400739 }
740}
741
Jamie Madill5b772312018-03-08 20:28:32 -0500742bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800743{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800744 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800745 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800746 case TextureType::_2D:
747 case TextureType::_2DArray:
748 case TextureType::_2DMultisample:
749 case TextureType::CubeMap:
750 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800751 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800752 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400753 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800754 default:
755 return false;
756 }
757}
758
Jamie Madill5b772312018-03-08 20:28:32 -0500759bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500760{
He Yunchaoced53ae2016-11-29 15:00:51 +0800761 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
762 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400763 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500764
765 switch (target)
766 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800767 case GL_FRAMEBUFFER:
768 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400769
He Yunchaoced53ae2016-11-29 15:00:51 +0800770 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800771 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400772 return (context->getExtensions().framebufferBlit ||
773 context->getClientMajorVersion() >= 3);
774
He Yunchaoced53ae2016-11-29 15:00:51 +0800775 default:
776 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500777 }
778}
779
Jamie Madill5b772312018-03-08 20:28:32 -0500780bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400781{
Jamie Madillc29968b2016-01-20 11:17:23 -0500782 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400783 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800784 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400785 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800786 case TextureType::_2D:
787 case TextureType::_2DArray:
788 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500789 maxDimension = caps.max2DTextureSize;
790 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800791 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800792 maxDimension = caps.maxCubeMapTextureSize;
793 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800794 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400795 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800796 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800797 maxDimension = caps.max3DTextureSize;
798 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800799 default:
800 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400801 }
802
Brandon Jones6cad5662017-06-14 13:25:13 -0700803 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400804}
805
Jamie Madill5b772312018-03-08 20:28:32 -0500806bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800807 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700808 GLint level,
809 GLsizei width,
810 GLsizei height,
811 GLsizei depth,
812 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400813{
Brandon Jones6cad5662017-06-14 13:25:13 -0700814 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400815 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700816 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400817 return false;
818 }
Austin Kinross08528e12015-10-07 16:24:40 -0700819 // TexSubImage parameters can be NPOT without textureNPOT extension,
820 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500821 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500822 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500823 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400824 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400825 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700826 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400827 return false;
828 }
829
830 if (!ValidMipLevel(context, target, level))
831 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700832 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400833 return false;
834 }
835
836 return true;
837}
838
Geoff Lang966c9402017-04-18 12:38:27 -0400839bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
840{
841 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
842 (size % blockSize == 0);
843}
844
Jamie Madill5b772312018-03-08 20:28:32 -0500845bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500846 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400847 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500848 GLsizei width,
849 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400850{
Geoff Langca271392017-04-05 12:30:00 -0400851 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400852 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400853 {
854 return false;
855 }
856
Geoff Lang966c9402017-04-18 12:38:27 -0400857 if (width < 0 || height < 0)
858 {
859 return false;
860 }
861
862 if (CompressedTextureFormatRequiresExactSize(internalFormat))
863 {
864 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
865 // block size for level 0 but WebGL disallows this.
866 bool smallerThanBlockSizeAllowed =
867 level > 0 || !context->getExtensions().webglCompatibility;
868
869 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
870 smallerThanBlockSizeAllowed) ||
871 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
872 smallerThanBlockSizeAllowed))
873 {
874 return false;
875 }
876 }
877
878 return true;
879}
880
Jamie Madill5b772312018-03-08 20:28:32 -0500881bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400882 GLenum internalFormat,
883 GLint xoffset,
884 GLint yoffset,
885 GLsizei width,
886 GLsizei height,
887 size_t textureWidth,
888 size_t textureHeight)
889{
890 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
891 if (!formatInfo.compressed)
892 {
893 return false;
894 }
895
Geoff Lang44ff5a72017-02-03 15:15:43 -0500896 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400897 {
898 return false;
899 }
900
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500901 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400902 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500903 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400904 yoffset % formatInfo.compressedBlockHeight != 0)
905 {
906 return false;
907 }
908
909 // Allowed to either have data that is a multiple of block size or is smaller than the block
910 // size but fills the entire mip
911 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
912 static_cast<size_t>(width) == textureWidth &&
913 static_cast<size_t>(height) == textureHeight;
914 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
915 (height % formatInfo.compressedBlockHeight) == 0;
916 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400917 {
918 return false;
919 }
920 }
921
Geoff Langd4f180b2013-09-24 13:57:44 -0400922 return true;
923}
924
Jamie Madill5b772312018-03-08 20:28:32 -0500925bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800926 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400927 GLsizei width,
928 GLsizei height,
929 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400930 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400931 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400932 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400933 GLsizei imageSize)
934{
Corentin Wallez336129f2017-10-17 15:55:40 -0400935 gl::Buffer *pixelUnpackBuffer =
936 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400937 if (pixelUnpackBuffer == nullptr && imageSize < 0)
938 {
939 // Checks are not required
940 return true;
941 }
942
943 // ...the data would be unpacked from the buffer object such that the memory reads required
944 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400945 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
946 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400947 const gl::Extents size(width, height, depth);
948 const auto &unpack = context->getGLState().getUnpackState();
949
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800950 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400951 GLuint endByte = 0;
952 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400953 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400954 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400955 return false;
956 }
957
Geoff Langff5b2d52016-09-07 11:32:23 -0400958 if (pixelUnpackBuffer)
959 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400960 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400961 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
962 checkedEndByte += checkedOffset;
963
964 if (!checkedEndByte.IsValid() ||
965 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
966 {
967 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400968 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400969 return false;
970 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800971 if (context->getExtensions().webglCompatibility &&
972 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
973 {
974 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
975 PixelUnpackBufferBoundForTransformFeedback);
976 return false;
977 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400978 }
979 else
980 {
981 ASSERT(imageSize >= 0);
982 if (pixels == nullptr && imageSize != 0)
983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500984 context->handleError(InvalidOperation()
985 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400986 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400987 }
988
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400989 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500991 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400992 return false;
993 }
994 }
995
996 return true;
997}
998
Corentin Wallezad3ae902018-03-09 13:40:42 -0500999bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -05001000{
Geoff Lang37dde692014-01-31 16:34:54 -05001001 switch (queryType)
1002 {
Corentin Wallezad3ae902018-03-09 13:40:42 -05001003 case QueryType::AnySamples:
1004 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001005 return context->getClientMajorVersion() >= 3 ||
1006 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001007 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +08001008 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -05001009 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +08001010 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001011 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +08001012 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001013 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +08001014 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +08001015 default:
1016 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001017 }
1018}
1019
Jamie Madill5b772312018-03-08 20:28:32 -05001020bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001021 GLenum type,
1022 GLboolean normalized,
1023 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001024 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001025 bool pureInteger)
1026{
1027 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001028 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1029 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1030 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1031 // parameter exceeds 255.
1032 constexpr GLsizei kMaxWebGLStride = 255;
1033 if (stride > kMaxWebGLStride)
1034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001035 context->handleError(InvalidValue()
1036 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001037 return false;
1038 }
1039
1040 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1041 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1042 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1043 // or an INVALID_OPERATION error is generated.
1044 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1045 size_t typeSize = GetVertexFormatTypeSize(internalType);
1046
1047 ASSERT(isPow2(typeSize) && typeSize > 0);
1048 size_t sizeMask = (typeSize - 1);
1049 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1050 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001051 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001052 return false;
1053 }
1054
1055 if ((stride & sizeMask) != 0)
1056 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001057 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001058 return false;
1059 }
1060
1061 return true;
1062}
1063
Jamie Madill5b772312018-03-08 20:28:32 -05001064Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001065{
He Yunchaoced53ae2016-11-29 15:00:51 +08001066 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1067 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1068 // or program object and INVALID_OPERATION if the provided name identifies an object
1069 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001070
Dian Xiang769769a2015-09-09 15:20:08 -07001071 Program *validProgram = context->getProgram(id);
1072
1073 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001074 {
Dian Xiang769769a2015-09-09 15:20:08 -07001075 if (context->getShader(id))
1076 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001077 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001078 }
1079 else
1080 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001081 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001082 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001083 }
Dian Xiang769769a2015-09-09 15:20:08 -07001084
1085 return validProgram;
1086}
1087
Jamie Madill5b772312018-03-08 20:28:32 -05001088Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001089{
1090 // See ValidProgram for spec details.
1091
1092 Shader *validShader = context->getShader(id);
1093
1094 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001095 {
Dian Xiang769769a2015-09-09 15:20:08 -07001096 if (context->getProgram(id))
1097 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001098 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001099 }
1100 else
1101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001102 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001103 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001104 }
Dian Xiang769769a2015-09-09 15:20:08 -07001105
1106 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001107}
1108
Geoff Langb1196682014-07-23 13:47:29 -04001109bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001110{
Geoff Langfa125c92017-10-24 13:01:46 -04001111 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001112 {
Geoff Langfa125c92017-10-24 13:01:46 -04001113 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1114 {
1115 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1116 return false;
1117 }
Jamie Madillb4472272014-07-03 10:38:55 -04001118
Geoff Langfa125c92017-10-24 13:01:46 -04001119 // Color attachment 0 is validated below because it is always valid
1120 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001121 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001122 {
Geoff Langfa125c92017-10-24 13:01:46 -04001123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001124 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001125 }
1126 }
1127 else
1128 {
1129 switch (attachment)
1130 {
Geoff Langfa125c92017-10-24 13:01:46 -04001131 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001132 case GL_DEPTH_ATTACHMENT:
1133 case GL_STENCIL_ATTACHMENT:
1134 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001135
He Yunchaoced53ae2016-11-29 15:00:51 +08001136 case GL_DEPTH_STENCIL_ATTACHMENT:
1137 if (!context->getExtensions().webglCompatibility &&
1138 context->getClientMajorVersion() < 3)
1139 {
Geoff Langfa125c92017-10-24 13:01:46 -04001140 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001141 return false;
1142 }
1143 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001144
He Yunchaoced53ae2016-11-29 15:00:51 +08001145 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001146 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001147 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001148 }
1149 }
1150
1151 return true;
1152}
1153
Jamie Madill5b772312018-03-08 20:28:32 -05001154bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001155 GLenum target,
1156 GLsizei samples,
1157 GLenum internalformat,
1158 GLsizei width,
1159 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001160{
1161 switch (target)
1162 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001163 case GL_RENDERBUFFER:
1164 break;
1165 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001166 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001167 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001168 }
1169
1170 if (width < 0 || height < 0 || samples < 0)
1171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001172 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001173 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001174 }
1175
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001176 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1177 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1178
1179 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001180 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001182 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001183 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001184 }
1185
1186 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1187 // 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 -08001188 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001189 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1190 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001193 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001194 }
1195
Geoff Langaae65a42014-05-26 12:43:44 -04001196 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001198 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001199 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001200 }
1201
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001202 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001203 if (handle == 0)
1204 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001206 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001207 }
1208
1209 return true;
1210}
1211
He Yunchaoced53ae2016-11-29 15:00:51 +08001212bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1213 GLenum target,
1214 GLenum attachment,
1215 GLenum renderbuffertarget,
1216 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001217{
Geoff Lange8afa902017-09-27 15:00:43 -04001218 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001220 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001221 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001222 }
1223
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001224 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001225
Jamie Madill84115c92015-04-23 15:00:07 -04001226 ASSERT(framebuffer);
1227 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001228 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001229 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001230 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001231 }
1232
Jamie Madillb4472272014-07-03 10:38:55 -04001233 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001234 {
Jamie Madillb4472272014-07-03 10:38:55 -04001235 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001236 }
1237
Jamie Madillab9d82c2014-01-21 16:38:14 -05001238 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1239 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1240 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1241 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1242 if (renderbuffer != 0)
1243 {
1244 if (!context->getRenderbuffer(renderbuffer))
1245 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001246 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001247 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001248 }
1249 }
1250
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001251 return true;
1252}
1253
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001254bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001255 GLint srcX0,
1256 GLint srcY0,
1257 GLint srcX1,
1258 GLint srcY1,
1259 GLint dstX0,
1260 GLint dstY0,
1261 GLint dstX1,
1262 GLint dstY1,
1263 GLbitfield mask,
1264 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001265{
1266 switch (filter)
1267 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001268 case GL_NEAREST:
1269 break;
1270 case GL_LINEAR:
1271 break;
1272 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001273 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001274 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 }
1276
1277 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001279 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001280 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001281 }
1282
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001283 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1284 // color buffer, leaving only nearest being unfiltered from above
1285 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001287 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001288 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289 }
1290
Jamie Madill51f40ec2016-06-15 14:06:00 -04001291 const auto &glState = context->getGLState();
1292 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1293 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001294
1295 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001297 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001298 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 }
1300
Jamie Madill427064d2018-04-13 16:20:34 -04001301 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001302 {
Jamie Madill48faf802014-11-06 15:27:22 -05001303 return false;
1304 }
1305
Jamie Madill427064d2018-04-13 16:20:34 -04001306 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001307 {
Jamie Madill48faf802014-11-06 15:27:22 -05001308 return false;
1309 }
1310
Qin Jiajiaaef92162018-02-27 13:51:44 +08001311 if (readFramebuffer->id() == drawFramebuffer->id())
1312 {
1313 context->handleError(InvalidOperation());
1314 return false;
1315 }
1316
Jamie Madille98b1b52018-03-08 09:47:23 -05001317 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001318 {
Geoff Langb1196682014-07-23 13:47:29 -04001319 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 }
1321
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001322 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1323 // always run it in order to avoid triggering driver bugs.
1324 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1325 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001326 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001327 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1328 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001329 }
1330
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1332
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001333 if (mask & GL_COLOR_BUFFER_BIT)
1334 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001335 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001336 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001337
He Yunchao66a41a22016-12-15 16:45:05 +08001338 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001339 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001340 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341
Geoff Langa15472a2015-08-11 11:48:03 -04001342 for (size_t drawbufferIdx = 0;
1343 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 {
Geoff Langa15472a2015-08-11 11:48:03 -04001345 const FramebufferAttachment *attachment =
1346 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1347 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001348 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001349 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350
Geoff Langb2f3d052013-08-13 12:49:27 -04001351 // The GL ES 3.0.2 spec (pg 193) states that:
1352 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001353 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1354 // as well
1355 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1356 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001357 // Changes with EXT_color_buffer_float:
1358 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001359 GLenum readComponentType = readFormat.info->componentType;
1360 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001361 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001362 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001363 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001364 drawComponentType == GL_SIGNED_NORMALIZED);
1365
1366 if (extensions.colorBufferFloat)
1367 {
1368 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1369 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1370
1371 if (readFixedOrFloat != drawFixedOrFloat)
1372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001373 context->handleError(InvalidOperation()
1374 << "If the read buffer contains fixed-point or "
1375 "floating-point values, the draw buffer must "
1376 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001377 return false;
1378 }
1379 }
1380 else if (readFixedPoint != drawFixedPoint)
1381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001382 context->handleError(InvalidOperation()
1383 << "If the read buffer contains fixed-point values, "
1384 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001385 return false;
1386 }
1387
1388 if (readComponentType == GL_UNSIGNED_INT &&
1389 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001391 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001392 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 }
1394
Jamie Madill6163c752015-12-07 16:32:59 -05001395 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001398 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 }
1400
Jamie Madilla3944d42016-07-22 22:13:26 -04001401 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001402 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001405 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406 }
Geoff Lange4915782017-04-12 15:19:07 -04001407
1408 if (context->getExtensions().webglCompatibility &&
1409 *readColorBuffer == *attachment)
1410 {
1411 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 InvalidOperation()
1413 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001414 return false;
1415 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 }
1417 }
1418
Jamie Madilla3944d42016-07-22 22:13:26 -04001419 if ((readFormat.info->componentType == GL_INT ||
1420 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1421 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001424 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 }
He Yunchao66a41a22016-12-15 16:45:05 +08001427 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1428 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1429 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1430 // situation is an application error that would lead to a crash in ANGLE.
1431 else if (drawFramebuffer->hasEnabledDrawBuffer())
1432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 context->handleError(
1434 InvalidOperation()
1435 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001436 return false;
1437 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001438 }
1439
He Yunchaoced53ae2016-11-29 15:00:51 +08001440 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001441 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1442 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001443 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001444 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001446 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001447 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001448 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001449 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001450
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001451 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001452 {
Kenneth Russell69382852017-07-21 16:38:44 -04001453 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001455 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001456 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001457 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001458
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001459 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001461 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001462 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001463 }
Geoff Lange4915782017-04-12 15:19:07 -04001464
1465 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001467 context->handleError(
1468 InvalidOperation()
1469 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001470 return false;
1471 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001472 }
He Yunchao66a41a22016-12-15 16:45:05 +08001473 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1474 else if (drawBuffer)
1475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001476 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1477 "depth/stencil attachment of a "
1478 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001479 return false;
1480 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001481 }
1482 }
1483
Martin Radeva3ed4572017-07-27 18:29:37 +03001484 // ANGLE_multiview, Revision 1:
1485 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001486 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1487 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1488 // views in the current read framebuffer is more than one.
1489 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001490 {
1491 context->handleError(InvalidFramebufferOperation()
1492 << "Attempt to read from a multi-view framebuffer.");
1493 return false;
1494 }
1495 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1496 {
1497 context->handleError(InvalidFramebufferOperation()
1498 << "Attempt to write to a multi-view framebuffer.");
1499 return false;
1500 }
1501
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001502 return true;
1503}
1504
Jamie Madill4928b7c2017-06-20 12:57:39 -04001505bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001506 GLint x,
1507 GLint y,
1508 GLsizei width,
1509 GLsizei height,
1510 GLenum format,
1511 GLenum type,
1512 GLsizei bufSize,
1513 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001514 GLsizei *columns,
1515 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001516 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001517{
1518 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001519 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001520 return false;
1521 }
1522
Brandon Jonesd1049182018-03-28 10:02:20 -07001523 GLsizei writeLength = 0;
1524 GLsizei writeColumns = 0;
1525 GLsizei writeRows = 0;
1526
1527 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1528 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001529 {
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001531 }
1532
Brandon Jonesd1049182018-03-28 10:02:20 -07001533 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001534 {
Geoff Langb1196682014-07-23 13:47:29 -04001535 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001536 }
1537
Brandon Jonesd1049182018-03-28 10:02:20 -07001538 SetRobustLengthParam(length, writeLength);
1539 SetRobustLengthParam(columns, writeColumns);
1540 SetRobustLengthParam(rows, writeRows);
1541
Jamie Madillc29968b2016-01-20 11:17:23 -05001542 return true;
1543}
1544
1545bool ValidateReadnPixelsEXT(Context *context,
1546 GLint x,
1547 GLint y,
1548 GLsizei width,
1549 GLsizei height,
1550 GLenum format,
1551 GLenum type,
1552 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001553 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001554{
1555 if (bufSize < 0)
1556 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001557 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001558 return false;
1559 }
1560
Geoff Lang62fce5b2016-09-30 10:46:35 -04001561 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001562 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001563}
Jamie Madill26e91952014-03-05 15:01:27 -05001564
Jamie Madill4928b7c2017-06-20 12:57:39 -04001565bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001566 GLint x,
1567 GLint y,
1568 GLsizei width,
1569 GLsizei height,
1570 GLenum format,
1571 GLenum type,
1572 GLsizei bufSize,
1573 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001574 GLsizei *columns,
1575 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001576 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001577{
Brandon Jonesd1049182018-03-28 10:02:20 -07001578 GLsizei writeLength = 0;
1579 GLsizei writeColumns = 0;
1580 GLsizei writeRows = 0;
1581
Geoff Lang62fce5b2016-09-30 10:46:35 -04001582 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001583 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001584 return false;
1585 }
1586
Brandon Jonesd1049182018-03-28 10:02:20 -07001587 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1588 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001589 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001590 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001591 }
1592
Brandon Jonesd1049182018-03-28 10:02:20 -07001593 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001594 {
1595 return false;
1596 }
1597
Brandon Jonesd1049182018-03-28 10:02:20 -07001598 SetRobustLengthParam(length, writeLength);
1599 SetRobustLengthParam(columns, writeColumns);
1600 SetRobustLengthParam(rows, writeRows);
1601
Geoff Lang62fce5b2016-09-30 10:46:35 -04001602 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001603}
1604
Jamie Madillf0e04492017-08-26 15:28:42 -04001605bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001606{
1607 if (!context->getExtensions().occlusionQueryBoolean &&
1608 !context->getExtensions().disjointTimerQuery)
1609 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001610 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001611 return false;
1612 }
1613
Olli Etuaho41997e72016-03-10 13:38:39 +02001614 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001615}
1616
Jamie Madillf0e04492017-08-26 15:28:42 -04001617bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001618{
1619 if (!context->getExtensions().occlusionQueryBoolean &&
1620 !context->getExtensions().disjointTimerQuery)
1621 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001622 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001623 return false;
1624 }
1625
Olli Etuaho41997e72016-03-10 13:38:39 +02001626 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001627}
1628
Jamie Madillf0e04492017-08-26 15:28:42 -04001629bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1630{
1631 if (!context->getExtensions().occlusionQueryBoolean &&
1632 !context->getExtensions().disjointTimerQuery)
1633 {
1634 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1635 return false;
1636 }
1637
1638 return true;
1639}
1640
Corentin Wallezad3ae902018-03-09 13:40:42 -05001641bool ValidateBeginQueryBase(gl::Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001642{
1643 if (!ValidQueryType(context, target))
1644 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001645 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001646 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001647 }
1648
1649 if (id == 0)
1650 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001651 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001652 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001653 }
1654
1655 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1656 // of zero, if the active query object name for <target> is non-zero (for the
1657 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1658 // the active query for either target is non-zero), if <id> is the name of an
1659 // existing query object whose type does not match <target>, or if <id> is the
1660 // active query object name for any query type, the error INVALID_OPERATION is
1661 // generated.
1662
1663 // Ensure no other queries are active
1664 // NOTE: If other queries than occlusion are supported, we will need to check
1665 // separately that:
1666 // a) The query ID passed is not the current active query for any target/type
1667 // b) There are no active queries for the requested target (and in the case
1668 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1669 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001671 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001673 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001674 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001675 }
1676
1677 Query *queryObject = context->getQuery(id, true, target);
1678
1679 // check that name was obtained with glGenQueries
1680 if (!queryObject)
1681 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001683 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001684 }
1685
1686 // check for type mismatch
1687 if (queryObject->getType() != target)
1688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001689 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001690 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001691 }
1692
1693 return true;
1694}
1695
Corentin Wallezad3ae902018-03-09 13:40:42 -05001696bool ValidateBeginQueryEXT(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697{
1698 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001699 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001701 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702 return false;
1703 }
1704
1705 return ValidateBeginQueryBase(context, target, id);
1706}
1707
Corentin Wallezad3ae902018-03-09 13:40:42 -05001708bool ValidateEndQueryBase(gl::Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001709{
1710 if (!ValidQueryType(context, target))
1711 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001712 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001713 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001714 }
1715
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001716 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001717
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001718 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001720 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001721 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001722 }
1723
Jamie Madill45c785d2014-05-13 14:09:34 -04001724 return true;
1725}
1726
Corentin Wallezad3ae902018-03-09 13:40:42 -05001727bool ValidateEndQueryEXT(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001728{
1729 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001730 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001732 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001733 return false;
1734 }
1735
1736 return ValidateEndQueryBase(context, target);
1737}
1738
Corentin Wallezad3ae902018-03-09 13:40:42 -05001739bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001740{
1741 if (!context->getExtensions().disjointTimerQuery)
1742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001743 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744 return false;
1745 }
1746
Corentin Wallezad3ae902018-03-09 13:40:42 -05001747 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001749 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750 return false;
1751 }
1752
1753 Query *queryObject = context->getQuery(id, true, target);
1754 if (queryObject == nullptr)
1755 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001756 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001757 return false;
1758 }
1759
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001760 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001761 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001762 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001763 return false;
1764 }
1765
1766 return true;
1767}
1768
Corentin Wallezad3ae902018-03-09 13:40:42 -05001769bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770{
Geoff Lang2186c382016-10-14 10:54:54 -04001771 if (numParams)
1772 {
1773 *numParams = 0;
1774 }
1775
Corentin Wallezad3ae902018-03-09 13:40:42 -05001776 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001777 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001778 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001779 return false;
1780 }
1781
1782 switch (pname)
1783 {
1784 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001785 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001787 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 return false;
1789 }
1790 break;
1791 case GL_QUERY_COUNTER_BITS_EXT:
1792 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001793 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001794 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001795 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001796 return false;
1797 }
1798 break;
1799 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001800 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001801 return false;
1802 }
1803
Geoff Lang2186c382016-10-14 10:54:54 -04001804 if (numParams)
1805 {
1806 // All queries return only one value
1807 *numParams = 1;
1808 }
1809
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001810 return true;
1811}
1812
Corentin Wallezad3ae902018-03-09 13:40:42 -05001813bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001814{
1815 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001816 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001817 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001818 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819 return false;
1820 }
1821
Geoff Lang2186c382016-10-14 10:54:54 -04001822 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001823}
1824
Geoff Lang2186c382016-10-14 10:54:54 -04001825bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001826 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001827 GLenum pname,
1828 GLsizei bufSize,
1829 GLsizei *length,
1830 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001831{
Geoff Lang2186c382016-10-14 10:54:54 -04001832 if (!ValidateRobustEntryPoint(context, bufSize))
1833 {
1834 return false;
1835 }
1836
Brandon Jonesd1049182018-03-28 10:02:20 -07001837 GLsizei numParams = 0;
1838
1839 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001840 {
1841 return false;
1842 }
1843
Brandon Jonesd1049182018-03-28 10:02:20 -07001844 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001845 {
1846 return false;
1847 }
1848
Brandon Jonesd1049182018-03-28 10:02:20 -07001849 SetRobustLengthParam(length, numParams);
1850
Geoff Lang2186c382016-10-14 10:54:54 -04001851 return true;
1852}
1853
1854bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1855{
1856 if (numParams)
1857 {
1858 *numParams = 0;
1859 }
1860
Corentin Wallezad3ae902018-03-09 13:40:42 -05001861 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862
1863 if (!queryObject)
1864 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001865 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001866 return false;
1867 }
1868
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001869 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001870 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001871 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001872 return false;
1873 }
1874
1875 switch (pname)
1876 {
1877 case GL_QUERY_RESULT_EXT:
1878 case GL_QUERY_RESULT_AVAILABLE_EXT:
1879 break;
1880
1881 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001882 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001883 return false;
1884 }
1885
Geoff Lang2186c382016-10-14 10:54:54 -04001886 if (numParams)
1887 {
1888 *numParams = 1;
1889 }
1890
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001891 return true;
1892}
1893
1894bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1895{
1896 if (!context->getExtensions().disjointTimerQuery)
1897 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001898 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001899 return false;
1900 }
Geoff Lang2186c382016-10-14 10:54:54 -04001901 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1902}
1903
1904bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1905 GLuint id,
1906 GLenum pname,
1907 GLsizei bufSize,
1908 GLsizei *length,
1909 GLint *params)
1910{
1911 if (!context->getExtensions().disjointTimerQuery)
1912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001913 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001914 return false;
1915 }
1916
1917 if (!ValidateRobustEntryPoint(context, bufSize))
1918 {
1919 return false;
1920 }
1921
Brandon Jonesd1049182018-03-28 10:02:20 -07001922 GLsizei numParams = 0;
1923
1924 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001925 {
1926 return false;
1927 }
1928
Brandon Jonesd1049182018-03-28 10:02:20 -07001929 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001930 {
1931 return false;
1932 }
1933
Brandon Jonesd1049182018-03-28 10:02:20 -07001934 SetRobustLengthParam(length, numParams);
1935
Geoff Lang2186c382016-10-14 10:54:54 -04001936 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001937}
1938
1939bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1940{
1941 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001942 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001943 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001944 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001945 return false;
1946 }
Geoff Lang2186c382016-10-14 10:54:54 -04001947 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1948}
1949
1950bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1951 GLuint id,
1952 GLenum pname,
1953 GLsizei bufSize,
1954 GLsizei *length,
1955 GLuint *params)
1956{
1957 if (!context->getExtensions().disjointTimerQuery &&
1958 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001960 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001961 return false;
1962 }
1963
1964 if (!ValidateRobustEntryPoint(context, bufSize))
1965 {
1966 return false;
1967 }
1968
Brandon Jonesd1049182018-03-28 10:02:20 -07001969 GLsizei numParams = 0;
1970
1971 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001972 {
1973 return false;
1974 }
1975
Brandon Jonesd1049182018-03-28 10:02:20 -07001976 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001977 {
1978 return false;
1979 }
1980
Brandon Jonesd1049182018-03-28 10:02:20 -07001981 SetRobustLengthParam(length, numParams);
1982
Geoff Lang2186c382016-10-14 10:54:54 -04001983 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001984}
1985
1986bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1987{
1988 if (!context->getExtensions().disjointTimerQuery)
1989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001990 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001991 return false;
1992 }
Geoff Lang2186c382016-10-14 10:54:54 -04001993 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1994}
1995
1996bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1997 GLuint id,
1998 GLenum pname,
1999 GLsizei bufSize,
2000 GLsizei *length,
2001 GLint64 *params)
2002{
2003 if (!context->getExtensions().disjointTimerQuery)
2004 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002005 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002006 return false;
2007 }
2008
2009 if (!ValidateRobustEntryPoint(context, bufSize))
2010 {
2011 return false;
2012 }
2013
Brandon Jonesd1049182018-03-28 10:02:20 -07002014 GLsizei numParams = 0;
2015
2016 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002017 {
2018 return false;
2019 }
2020
Brandon Jonesd1049182018-03-28 10:02:20 -07002021 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002022 {
2023 return false;
2024 }
2025
Brandon Jonesd1049182018-03-28 10:02:20 -07002026 SetRobustLengthParam(length, numParams);
2027
Geoff Lang2186c382016-10-14 10:54:54 -04002028 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002029}
2030
2031bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2032{
2033 if (!context->getExtensions().disjointTimerQuery)
2034 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002035 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002036 return false;
2037 }
Geoff Lang2186c382016-10-14 10:54:54 -04002038 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2039}
2040
2041bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2042 GLuint id,
2043 GLenum pname,
2044 GLsizei bufSize,
2045 GLsizei *length,
2046 GLuint64 *params)
2047{
2048 if (!context->getExtensions().disjointTimerQuery)
2049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002051 return false;
2052 }
2053
2054 if (!ValidateRobustEntryPoint(context, bufSize))
2055 {
2056 return false;
2057 }
2058
Brandon Jonesd1049182018-03-28 10:02:20 -07002059 GLsizei numParams = 0;
2060
2061 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002062 {
2063 return false;
2064 }
2065
Brandon Jonesd1049182018-03-28 10:02:20 -07002066 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002067 {
2068 return false;
2069 }
2070
Brandon Jonesd1049182018-03-28 10:02:20 -07002071 SetRobustLengthParam(length, numParams);
2072
Geoff Lang2186c382016-10-14 10:54:54 -04002073 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002074}
2075
Jamie Madill5b772312018-03-08 20:28:32 -05002076bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002077 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002078 GLint location,
2079 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002080 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002081{
Jiajia Qin5451d532017-11-16 17:16:34 +08002082 // TODO(Jiajia): Add image uniform check in future.
2083 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002084 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002085 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002086 return false;
2087 }
2088
Jiajia Qin5451d532017-11-16 17:16:34 +08002089 if (!program)
2090 {
2091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2092 return false;
2093 }
2094
2095 if (!program->isLinked())
2096 {
2097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2098 return false;
2099 }
2100
2101 if (location == -1)
2102 {
2103 // Silently ignore the uniform command
2104 return false;
2105 }
2106
2107 const auto &uniformLocations = program->getUniformLocations();
2108 size_t castedLocation = static_cast<size_t>(location);
2109 if (castedLocation >= uniformLocations.size())
2110 {
2111 context->handleError(InvalidOperation() << "Invalid uniform location");
2112 return false;
2113 }
2114
2115 const auto &uniformLocation = uniformLocations[castedLocation];
2116 if (uniformLocation.ignored)
2117 {
2118 // Silently ignore the uniform command
2119 return false;
2120 }
2121
2122 if (!uniformLocation.used())
2123 {
2124 context->handleError(InvalidOperation());
2125 return false;
2126 }
2127
2128 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2129
2130 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002131 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002132 {
2133 context->handleError(InvalidOperation());
2134 return false;
2135 }
2136
2137 *uniformOut = &uniform;
2138 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002139}
2140
Jamie Madill5b772312018-03-08 20:28:32 -05002141bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002142 GLenum uniformType,
2143 GLsizei count,
2144 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002145{
Jiajia Qin5451d532017-11-16 17:16:34 +08002146 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2147 // It is compatible with INT or BOOL.
2148 // Do these cheap tests first, for a little extra speed.
2149 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002150 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002151 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002152 }
2153
Jiajia Qin5451d532017-11-16 17:16:34 +08002154 if (IsSamplerType(uniformType))
2155 {
2156 // Check that the values are in range.
2157 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2158 for (GLsizei i = 0; i < count; ++i)
2159 {
2160 if (value[i] < 0 || value[i] >= max)
2161 {
2162 context->handleError(InvalidValue() << "sampler uniform value out of range");
2163 return false;
2164 }
2165 }
2166 return true;
2167 }
2168
2169 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2170 return false;
2171}
2172
Jamie Madill5b772312018-03-08 20:28:32 -05002173bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002174{
2175 // Check that the value type is compatible with uniform type.
2176 // Do the cheaper test first, for a little extra speed.
2177 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2178 {
2179 return true;
2180 }
2181
2182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2183 return false;
2184}
2185
Jamie Madill5b772312018-03-08 20:28:32 -05002186bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002187{
2188 // Check that the value type is compatible with uniform type.
2189 if (valueType == uniformType)
2190 {
2191 return true;
2192 }
2193
2194 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2195 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002196}
2197
Jamie Madill5b772312018-03-08 20:28:32 -05002198bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002199{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002200 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002201 gl::Program *programObject = context->getGLState().getProgram();
2202 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2203 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002204}
2205
Jamie Madill5b772312018-03-08 20:28:32 -05002206bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002207{
2208 const LinkedUniform *uniform = nullptr;
2209 gl::Program *programObject = context->getGLState().getProgram();
2210 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2211 ValidateUniform1ivValue(context, uniform->type, count, value);
2212}
2213
Jamie Madill5b772312018-03-08 20:28:32 -05002214bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002215 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002216 GLint location,
2217 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002218 GLboolean transpose)
2219{
Geoff Lang92019432017-11-20 13:09:34 -05002220 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002222 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002223 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002224 }
2225
Jamie Madill62d31cb2015-09-11 13:25:51 -04002226 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002227 gl::Program *programObject = context->getGLState().getProgram();
2228 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2229 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002230}
2231
Jamie Madill5b772312018-03-08 20:28:32 -05002232bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002233{
2234 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002236 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002237 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002238 }
2239
Jamie Madill0af26e12015-03-05 19:54:33 -05002240 const Caps &caps = context->getCaps();
2241
Jamie Madill893ab082014-05-16 16:56:10 -04002242 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2243 {
2244 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2245
Jamie Madill0af26e12015-03-05 19:54:33 -05002246 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002248 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002249 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002250 }
2251 }
2252
2253 switch (pname)
2254 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002255 case GL_TEXTURE_BINDING_2D:
2256 case GL_TEXTURE_BINDING_CUBE_MAP:
2257 case GL_TEXTURE_BINDING_3D:
2258 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002259 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002260 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002261 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2262 if (!context->getExtensions().textureRectangle)
2263 {
2264 context->handleError(InvalidEnum()
2265 << "ANGLE_texture_rectangle extension not present");
2266 return false;
2267 }
2268 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002269 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2270 if (!context->getExtensions().eglStreamConsumerExternal &&
2271 !context->getExtensions().eglImageExternal)
2272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002273 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2274 "nor GL_OES_EGL_image_external "
2275 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002276 return false;
2277 }
2278 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002279
He Yunchaoced53ae2016-11-29 15:00:51 +08002280 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2281 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002282 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002283 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2284 ASSERT(readFramebuffer);
2285
Jamie Madill427064d2018-04-13 16:20:34 -04002286 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002287 {
Geoff Langb1196682014-07-23 13:47:29 -04002288 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002289 }
2290
Jamie Madille98b1b52018-03-08 09:47:23 -05002291 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002292 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002293 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002294 return false;
2295 }
2296
Jamie Madille98b1b52018-03-08 09:47:23 -05002297 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002298 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002300 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002301 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002302 }
2303 }
2304 break;
2305
He Yunchaoced53ae2016-11-29 15:00:51 +08002306 default:
2307 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002308 }
2309
2310 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002311 if (*numParams == 0)
2312 {
2313 return false;
2314 }
2315
2316 return true;
2317}
2318
Brandon Jonesd1049182018-03-28 10:02:20 -07002319bool ValidateGetBooleanvRobustANGLE(Context *context,
2320 GLenum pname,
2321 GLsizei bufSize,
2322 GLsizei *length,
2323 GLboolean *params)
2324{
2325 GLenum nativeType;
2326 unsigned int numParams = 0;
2327
2328 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2329 {
2330 return false;
2331 }
2332
2333 SetRobustLengthParam(length, numParams);
2334
2335 return true;
2336}
2337
2338bool ValidateGetFloatvRobustANGLE(Context *context,
2339 GLenum pname,
2340 GLsizei bufSize,
2341 GLsizei *length,
2342 GLfloat *params)
2343{
2344 GLenum nativeType;
2345 unsigned int numParams = 0;
2346
2347 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2348 {
2349 return false;
2350 }
2351
2352 SetRobustLengthParam(length, numParams);
2353
2354 return true;
2355}
2356
2357bool ValidateGetIntegervRobustANGLE(Context *context,
2358 GLenum pname,
2359 GLsizei bufSize,
2360 GLsizei *length,
2361 GLint *data)
2362{
2363 GLenum nativeType;
2364 unsigned int numParams = 0;
2365
2366 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2367 {
2368 return false;
2369 }
2370
2371 SetRobustLengthParam(length, numParams);
2372
2373 return true;
2374}
2375
2376bool ValidateGetInteger64vRobustANGLE(Context *context,
2377 GLenum pname,
2378 GLsizei bufSize,
2379 GLsizei *length,
2380 GLint64 *data)
2381{
2382 GLenum nativeType;
2383 unsigned int numParams = 0;
2384
2385 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2386 {
2387 return false;
2388 }
2389
2390 if (nativeType == GL_INT_64_ANGLEX)
2391 {
2392 CastStateValues(context, nativeType, pname, numParams, data);
2393 return false;
2394 }
2395
2396 SetRobustLengthParam(length, numParams);
2397 return true;
2398}
2399
Jamie Madill5b772312018-03-08 20:28:32 -05002400bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002401 GLenum pname,
2402 GLsizei bufSize,
2403 GLenum *nativeType,
2404 unsigned int *numParams)
2405{
2406 if (!ValidateRobustEntryPoint(context, bufSize))
2407 {
2408 return false;
2409 }
2410
2411 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2412 {
2413 return false;
2414 }
2415
2416 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002417 {
2418 return false;
2419 }
2420
2421 return true;
2422}
2423
Jamie Madill5b772312018-03-08 20:28:32 -05002424bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002425 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002426 GLint level,
2427 GLenum internalformat,
2428 bool isSubImage,
2429 GLint xoffset,
2430 GLint yoffset,
2431 GLint zoffset,
2432 GLint x,
2433 GLint y,
2434 GLsizei width,
2435 GLsizei height,
2436 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002437 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002438{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002439 TextureType texType = TextureTargetToType(target);
2440
Brandon Jones6cad5662017-06-14 13:25:13 -07002441 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002442 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002443 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2444 return false;
2445 }
2446
2447 if (width < 0 || height < 0)
2448 {
2449 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002450 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002451 }
2452
He Yunchaoced53ae2016-11-29 15:00:51 +08002453 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2454 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002456 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002457 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002458 }
2459
2460 if (border != 0)
2461 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002462 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002463 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002464 }
2465
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002466 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002467 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002468 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002469 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002470 }
2471
Jamie Madille98b1b52018-03-08 09:47:23 -05002472 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002473 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002474 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002475 {
Geoff Langb1196682014-07-23 13:47:29 -04002476 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002477 }
2478
Jamie Madille98b1b52018-03-08 09:47:23 -05002479 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002480 {
Geoff Langb1196682014-07-23 13:47:29 -04002481 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002482 }
2483
Martin Radev138064f2016-07-15 12:03:41 +03002484 if (readFramebuffer->getReadBufferState() == GL_NONE)
2485 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002486 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002487 return false;
2488 }
2489
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002490 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2491 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002492 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002493 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002494 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2495 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002496 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002497 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002498 return false;
2499 }
2500
Martin Radev04e2c3b2017-07-27 16:54:35 +03002501 // ANGLE_multiview spec, Revision 1:
2502 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2503 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002504 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2505 // framebuffer is more than one.
2506 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002507 {
2508 context->handleError(InvalidFramebufferOperation()
2509 << "The active read framebuffer object has multiview attachments.");
2510 return false;
2511 }
2512
Geoff Langaae65a42014-05-26 12:43:44 -04002513 const gl::Caps &caps = context->getCaps();
2514
Geoff Langaae65a42014-05-26 12:43:44 -04002515 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002516 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002517 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002518 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002519 maxDimension = caps.max2DTextureSize;
2520 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002521
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002522 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002523 maxDimension = caps.maxCubeMapTextureSize;
2524 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002525
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002526 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002527 maxDimension = caps.maxRectangleTextureSize;
2528 break;
2529
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002530 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002531 maxDimension = caps.max2DTextureSize;
2532 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002533
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002534 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002535 maxDimension = caps.max3DTextureSize;
2536 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002537
He Yunchaoced53ae2016-11-29 15:00:51 +08002538 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002539 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002540 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002541 }
2542
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002543 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002544 if (!texture)
2545 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002546 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002547 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002548 }
2549
Geoff Lang69cce582015-09-17 13:20:36 -04002550 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002552 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002553 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002554 }
2555
Geoff Langca271392017-04-05 12:30:00 -04002556 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002557 isSubImage ? *texture->getFormat(target, level).info
2558 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002559
Geoff Lang966c9402017-04-18 12:38:27 -04002560 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002562 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002563 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002564 }
2565
2566 if (isSubImage)
2567 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002568 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2569 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2570 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002572 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002573 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002574 }
2575 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002576 else
2577 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002578 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002579 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002580 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002581 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002582 }
2583
Geoff Langeb66a6e2016-10-31 13:06:12 -04002584 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002585 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002586 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002587 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002588 }
2589
2590 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002591 if (static_cast<int>(width) > maxLevelDimension ||
2592 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002593 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002594 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002595 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002596 }
2597 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002598
Jamie Madill0c8abca2016-07-22 20:21:26 -04002599 if (textureFormatOut)
2600 {
2601 *textureFormatOut = texture->getFormat(target, level);
2602 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002603
2604 // Detect texture copying feedback loops for WebGL.
2605 if (context->getExtensions().webglCompatibility)
2606 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002607 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002608 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002609 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002610 return false;
2611 }
2612 }
2613
Jamie Madill560a8d82014-05-21 13:06:20 -04002614 return true;
2615}
2616
Jamie Madill493f9572018-05-24 19:52:15 -04002617bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002618{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002619 const Extensions &extensions = context->getExtensions();
2620
Jamie Madill1aeb1312014-06-20 13:21:25 -04002621 switch (mode)
2622 {
Jamie Madill493f9572018-05-24 19:52:15 -04002623 case PrimitiveMode::Points:
2624 case PrimitiveMode::Lines:
2625 case PrimitiveMode::LineLoop:
2626 case PrimitiveMode::LineStrip:
2627 case PrimitiveMode::Triangles:
2628 case PrimitiveMode::TriangleStrip:
2629 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002630 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002631
Jamie Madill493f9572018-05-24 19:52:15 -04002632 case PrimitiveMode::LinesAdjacency:
2633 case PrimitiveMode::LineStripAdjacency:
2634 case PrimitiveMode::TrianglesAdjacency:
2635 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002636 if (!extensions.geometryShader)
2637 {
2638 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2639 return false;
2640 }
2641 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002642 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002643 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002644 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002645 }
2646
Jamie Madill250d33f2014-06-06 17:09:03 -04002647 if (count < 0)
2648 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002649 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002650 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002651 }
2652
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002653 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002654
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002655 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2656 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2657 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2658 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002659 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002660 // Check for mapped buffers
2661 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002662 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002663 {
2664 context->handleError(InvalidOperation());
2665 return false;
2666 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002667 }
2668
Jamie Madillcbcde722017-01-06 14:50:00 -05002669 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2670 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002671 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002672 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002673 {
Ken Russellb9f92502018-01-27 19:00:26 -08002674 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002675 const FramebufferAttachment *dsAttachment =
2676 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002677 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2678 ASSERT(stencilBits <= 8);
2679
Jinyoung Hur85769f02015-10-20 17:08:44 -04002680 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002681 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002682 {
Ken Russellb9f92502018-01-27 19:00:26 -08002683 GLuint maxStencilValue = (1 << stencilBits) - 1;
2684
2685 bool differentRefs =
2686 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2687 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2688 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2689 (depthStencilState.stencilBackWritemask & maxStencilValue);
2690 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2691 (depthStencilState.stencilBackMask & maxStencilValue);
2692
2693 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002694 {
Ken Russellb9f92502018-01-27 19:00:26 -08002695 if (!extensions.webglCompatibility)
2696 {
Jamie Madilla2f043d2018-07-10 17:21:20 -04002697 WARN() << "This ANGLE implementation does not support separate front/back "
2698 "stencil writemasks, reference values, or stencil mask values.";
Ken Russellb9f92502018-01-27 19:00:26 -08002699 }
2700 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2701 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002702 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002703 }
Jamie Madillac528012014-06-20 13:21:23 -04002704 }
2705
Jamie Madill427064d2018-04-13 16:20:34 -04002706 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002707 {
Geoff Langb1196682014-07-23 13:47:29 -04002708 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002709 }
2710
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002711 // If we are running GLES1, there is no current program.
2712 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002713 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002714
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002715 gl::Program *program = state.getProgram();
2716 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002717 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002719 return false;
2720 }
Martin Radev7e69f762017-07-27 14:54:13 +03002721
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002722 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2723 // vertex shader stage or fragment shader stage is a undefined behaviour.
2724 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2725 // produce undefined result.
2726 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2727 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002728 {
2729 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002730 << "It is a undefined behaviour to render without "
2731 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002732 return false;
2733 }
Martin Radevffe754b2017-07-31 10:38:07 +03002734
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002735 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002736 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002737 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002738 return false;
2739 }
2740
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002741 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002742 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002743 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2744 const int framebufferNumViews = framebuffer->getNumViews();
2745 if (framebufferNumViews != programNumViews)
2746 {
2747 context->handleError(InvalidOperation()
2748 << "The number of views in the active program "
2749 "and draw framebuffer does not match.");
2750 return false;
2751 }
2752
2753 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2754 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2755 framebufferNumViews > 1)
2756 {
2757 context->handleError(InvalidOperation()
2758 << "There is an active transform feedback object "
2759 "when the number of views in the active draw "
2760 "framebuffer is greater than 1.");
2761 return false;
2762 }
2763
2764 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2765 state.isQueryActive(QueryType::TimeElapsed))
2766 {
2767 context->handleError(InvalidOperation()
2768 << "There is an active query for target "
2769 "GL_TIME_ELAPSED_EXT when the number of "
2770 "views in the active draw framebuffer is "
2771 "greater than 1.");
2772 return false;
2773 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002774 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002775
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002776 // Do geometry shader specific validations
2777 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002778 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002779 if (!IsCompatibleDrawModeWithGeometryShader(
2780 mode, program->getGeometryShaderInputPrimitiveType()))
2781 {
2782 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2783 IncompatibleDrawModeAgainstGeometryShader);
2784 return false;
2785 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002786 }
Geoff Lange0cff192017-05-30 13:04:56 -04002787
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002788 // Uniform buffer validation
2789 for (unsigned int uniformBlockIndex = 0;
2790 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002791 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002792 const gl::InterfaceBlock &uniformBlock =
2793 program->getUniformBlockByIndex(uniformBlockIndex);
2794 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2795 const OffsetBindingPointer<Buffer> &uniformBuffer =
2796 state.getIndexedUniformBuffer(blockBinding);
2797
2798 if (uniformBuffer.get() == nullptr)
2799 {
2800 // undefined behaviour
2801 context->handleError(
2802 InvalidOperation()
2803 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2804 return false;
2805 }
2806
2807 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2808 if (uniformBufferSize < uniformBlock.dataSize)
2809 {
2810 // undefined behaviour
2811 context->handleError(
2812 InvalidOperation()
2813 << "It is undefined behaviour to use a uniform buffer that is too small.");
2814 return false;
2815 }
2816
2817 if (extensions.webglCompatibility &&
2818 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2819 {
2820 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2821 UniformBufferBoundForTransformFeedback);
2822 return false;
2823 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002824 }
2825
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002826 // Do some additonal WebGL-specific validation
2827 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002828 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002829 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2830 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2831 transformFeedbackObject->buffersBoundForOtherUse())
2832 {
2833 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2834 TransformFeedbackBufferDoubleBound);
2835 return false;
2836 }
2837 // Detect rendering feedback loops for WebGL.
2838 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2839 {
2840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2841 return false;
2842 }
2843
2844 // Detect that the vertex shader input types match the attribute types
2845 if (!ValidateVertexShaderAttributeTypeMatch(context))
2846 {
2847 return false;
2848 }
2849
2850 // Detect that the color buffer types match the fragment shader output types
2851 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2852 {
2853 return false;
2854 }
Jamie Madillac43aaa2018-07-31 11:22:13 -04002855
2856 if (count > 0)
2857 {
2858 const VertexArray *vao = context->getGLState().getVertexArray();
2859 if (vao->hasTransformFeedbackBindingConflict(context))
2860 {
2861 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2862 VertexBufferBoundForTransformFeedback);
2863 return false;
2864 }
2865 }
Geoff Lange0cff192017-05-30 13:04:56 -04002866 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002867 }
2868
Jamie Madill9fdaa492018-02-16 10:52:11 -05002869 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002870}
2871
Jamie Madill5b772312018-03-08 20:28:32 -05002872bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002873 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002874 GLint first,
2875 GLsizei count,
2876 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002877{
Jamie Madillfd716582014-06-06 17:09:04 -04002878 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002879 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002880 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002881 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002882 }
2883
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002884 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002885 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002886 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002887 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002888 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002889 if (!ValidateTransformFeedbackPrimitiveMode(context,
2890 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002891 {
James Darpinian30b604d2018-03-12 17:26:57 -07002892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2893 return false;
2894 }
2895
2896 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2897 {
2898 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2899 return false;
2900 }
Jamie Madillfd716582014-06-06 17:09:04 -04002901 }
2902
Jiajia Qind9671222016-11-29 16:30:31 +08002903 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002904 {
2905 return false;
2906 }
2907
Corentin Wallez71168a02016-12-19 15:11:18 -08002908 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002909 // - first < 0 has been checked as an error condition.
2910 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002911 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002912 ASSERT(first >= 0);
2913 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002914 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002915 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2916 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2917 {
2918 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2919 return false;
2920 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002921
Jamie Madill9fdaa492018-02-16 10:52:11 -05002922 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2923 {
2924 return false;
2925 }
Jamie Madillfd716582014-06-06 17:09:04 -04002926 }
2927
2928 return true;
2929}
2930
He Yunchaoced53ae2016-11-29 15:00:51 +08002931bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002932 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002933 GLint first,
2934 GLsizei count,
2935 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002936{
Geoff Lang63c5a592017-09-27 14:08:16 -04002937 if (!context->getExtensions().instancedArrays)
2938 {
2939 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2940 return false;
2941 }
2942
Corentin Wallez170efbf2017-05-02 13:45:01 -04002943 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002944 {
2945 return false;
2946 }
2947
Corentin Wallez0dc97812017-06-22 14:38:44 -04002948 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002949}
2950
Jamie Madill493f9572018-05-24 19:52:15 -04002951bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002952{
Jamie Madill250d33f2014-06-06 17:09:03 -04002953 switch (type)
2954 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002955 case GL_UNSIGNED_BYTE:
2956 case GL_UNSIGNED_SHORT:
2957 break;
2958 case GL_UNSIGNED_INT:
2959 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2960 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002961 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002962 return false;
2963 }
2964 break;
2965 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002967 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002968 }
2969
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002970 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002971
2972 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002973 if (curTransformFeedback && curTransformFeedback->isActive() &&
2974 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002975 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002976 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2977 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2978 if (context->getExtensions().geometryShader)
2979 {
2980 if (!ValidateTransformFeedbackPrimitiveMode(
2981 context, curTransformFeedback->getPrimitiveMode(), mode))
2982 {
2983 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2984 return false;
2985 }
2986 }
2987 else
2988 {
2989 // It is an invalid operation to call DrawElements, DrawRangeElements or
2990 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2991 // 86)
2992 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2993 UnsupportedDrawModeForTransformFeedback);
2994 return false;
2995 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002996 }
2997
Jiajia Qind9671222016-11-29 16:30:31 +08002998 return true;
2999}
3000
Jamie Madill5b772312018-03-08 20:28:32 -05003001bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003002 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003003 GLsizei count,
3004 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003005 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003006 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003007{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003008 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003009 return false;
3010
3011 const State &state = context->getGLState();
3012
Corentin Wallez170efbf2017-05-02 13:45:01 -04003013 if (!ValidateDrawBase(context, mode, count))
3014 {
3015 return false;
3016 }
3017
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003018 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
3019 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3020 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3021 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04003022 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003023 // Check for mapped buffers
3024 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04003025 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003026 {
3027 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3028 return false;
3029 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003030 }
3031
He Yunchaoced53ae2016-11-29 15:00:51 +08003032 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003033 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003034
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003035 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3036
3037 if (context->getExtensions().webglCompatibility)
3038 {
3039 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3040 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3041 {
3042 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3043 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3044 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003045 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003046 return false;
3047 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003048
3049 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3050 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3051 // error is generated.
3052 if (reinterpret_cast<intptr_t>(indices) < 0)
3053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003054 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003055 return false;
3056 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003057 }
3058
3059 if (context->getExtensions().webglCompatibility ||
3060 !context->getGLState().areClientArraysEnabled())
3061 {
Brandon Jones2a018152018-06-08 15:59:26 -07003062 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003063 {
3064 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003065 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3066 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003067 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003068 return false;
3069 }
3070 }
3071
Jamie Madill9fdaa492018-02-16 10:52:11 -05003072 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003073 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003074 // This is an application error that would normally result in a crash, but we catch it and
3075 // return an error
3076 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3077 return false;
3078 }
3079
3080 if (count > 0 && elementArrayBuffer)
3081 {
3082 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3083 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3084 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3085 constexpr uint64_t kMaxTypeSize = 8;
3086 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3087 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3088 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3089
3090 uint64_t typeSize = typeBytes;
3091 uint64_t elementCount = static_cast<uint64_t>(count);
3092 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3093
3094 // Doing the multiplication here is overflow-safe
3095 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3096
3097 // The offset can be any value, check for overflows
3098 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3099 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003100 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003101 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3102 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003103 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003104
3105 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3106 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003107 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3109 return false;
3110 }
3111
3112 ASSERT(isPow2(typeSize) && typeSize > 0);
3113 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3114 {
3115 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003116 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003117 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003118
3119 if (context->getExtensions().webglCompatibility &&
3120 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3121 {
3122 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3123 ElementArrayBufferBoundForTransformFeedback);
3124 return false;
3125 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003126 }
3127
Jamie Madillac43aaa2018-07-31 11:22:13 -04003128 if (context->getExtensions().robustBufferAccessBehavior || count == 0)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003129 {
Jamie Madillac43aaa2018-07-31 11:22:13 -04003130 // Special checks are needed for client attribs. But we don't need to validate overflows.
3131 if (!ValidateDrawClientAttribs(context))
Jamie Madill9fdaa492018-02-16 10:52:11 -05003132 {
3133 return false;
3134 }
3135 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003136 else
3137 {
3138 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003139 const DrawCallParams &params = context->getParams<DrawCallParams>();
3140 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3141 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003142
3143 // If we use an index greater than our maximum supported index range, return an error.
3144 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3145 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003146 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003147 {
3148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3149 return false;
3150 }
3151
Jamie Madill6f5444d2018-03-14 10:08:11 -04003152 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3153 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003154 {
3155 return false;
3156 }
3157
3158 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003159 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003160 }
3161
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003162 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003163}
3164
Jamie Madill5b772312018-03-08 20:28:32 -05003165bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003166 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003167 GLsizei count,
3168 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003169 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003170 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003171{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003172 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003173}
3174
Geoff Lang3edfe032015-09-04 16:38:24 -04003175bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003176 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003177 GLsizei count,
3178 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003179 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003180 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003181{
Geoff Lang63c5a592017-09-27 14:08:16 -04003182 if (!context->getExtensions().instancedArrays)
3183 {
3184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3185 return false;
3186 }
3187
Corentin Wallez170efbf2017-05-02 13:45:01 -04003188 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003189 {
3190 return false;
3191 }
3192
Corentin Wallez0dc97812017-06-22 14:38:44 -04003193 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003194}
3195
He Yunchaoced53ae2016-11-29 15:00:51 +08003196bool ValidateFramebufferTextureBase(Context *context,
3197 GLenum target,
3198 GLenum attachment,
3199 GLuint texture,
3200 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003201{
Geoff Lange8afa902017-09-27 15:00:43 -04003202 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003203 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003204 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003205 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003206 }
3207
3208 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003209 {
3210 return false;
3211 }
3212
Jamie Madill55ec3b12014-07-03 10:38:57 -04003213 if (texture != 0)
3214 {
3215 gl::Texture *tex = context->getTexture(texture);
3216
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003217 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003219 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003220 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003221 }
3222
3223 if (level < 0)
3224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003225 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003226 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003227 }
3228 }
3229
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003230 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003231 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003232
Jamie Madill84115c92015-04-23 15:00:07 -04003233 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003236 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003237 }
3238
3239 return true;
3240}
3241
Geoff Langb1196682014-07-23 13:47:29 -04003242bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003243{
3244 if (program == 0)
3245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003246 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003247 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003248 }
3249
Dian Xiang769769a2015-09-09 15:20:08 -07003250 gl::Program *programObject = GetValidProgram(context, program);
3251 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003252 {
3253 return false;
3254 }
3255
Jamie Madill0063c512014-08-25 15:47:53 -04003256 if (!programObject || !programObject->isLinked())
3257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003259 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003260 }
3261
Geoff Lang7dd2e102014-11-10 15:19:26 -05003262 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003263 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003264 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003265 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003266 }
3267
Jamie Madill0063c512014-08-25 15:47:53 -04003268 return true;
3269}
3270
Geoff Langf41d0ee2016-10-07 13:04:23 -04003271static bool ValidateSizedGetUniform(Context *context,
3272 GLuint program,
3273 GLint location,
3274 GLsizei bufSize,
3275 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003276{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003277 if (length)
3278 {
3279 *length = 0;
3280 }
3281
Jamie Madill78f41802014-08-25 15:47:55 -04003282 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003283 {
Jamie Madill78f41802014-08-25 15:47:55 -04003284 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003285 }
3286
Geoff Langf41d0ee2016-10-07 13:04:23 -04003287 if (bufSize < 0)
3288 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003289 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003290 return false;
3291 }
3292
Jamie Madilla502c742014-08-28 17:19:13 -04003293 gl::Program *programObject = context->getProgram(program);
3294 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003295
Jamie Madill78f41802014-08-25 15:47:55 -04003296 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003297 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003298 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003299 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003300 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003302 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003303 }
3304
Geoff Langf41d0ee2016-10-07 13:04:23 -04003305 if (length)
3306 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003307 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003308 }
3309
Jamie Madill0063c512014-08-25 15:47:53 -04003310 return true;
3311}
3312
He Yunchaoced53ae2016-11-29 15:00:51 +08003313bool ValidateGetnUniformfvEXT(Context *context,
3314 GLuint program,
3315 GLint location,
3316 GLsizei bufSize,
3317 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003318{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003319 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003320}
3321
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003322bool ValidateGetnUniformfvRobustANGLE(Context *context,
3323 GLuint program,
3324 GLint location,
3325 GLsizei bufSize,
3326 GLsizei *length,
3327 GLfloat *params)
3328{
3329 UNIMPLEMENTED();
3330 return false;
3331}
3332
He Yunchaoced53ae2016-11-29 15:00:51 +08003333bool ValidateGetnUniformivEXT(Context *context,
3334 GLuint program,
3335 GLint location,
3336 GLsizei bufSize,
3337 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003338{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003339 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3340}
3341
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003342bool ValidateGetnUniformivRobustANGLE(Context *context,
3343 GLuint program,
3344 GLint location,
3345 GLsizei bufSize,
3346 GLsizei *length,
3347 GLint *params)
3348{
3349 UNIMPLEMENTED();
3350 return false;
3351}
3352
3353bool ValidateGetnUniformuivRobustANGLE(Context *context,
3354 GLuint program,
3355 GLint location,
3356 GLsizei bufSize,
3357 GLsizei *length,
3358 GLuint *params)
3359{
3360 UNIMPLEMENTED();
3361 return false;
3362}
3363
Geoff Langf41d0ee2016-10-07 13:04:23 -04003364bool ValidateGetUniformfvRobustANGLE(Context *context,
3365 GLuint program,
3366 GLint location,
3367 GLsizei bufSize,
3368 GLsizei *length,
3369 GLfloat *params)
3370{
3371 if (!ValidateRobustEntryPoint(context, bufSize))
3372 {
3373 return false;
3374 }
3375
Brandon Jonesd1049182018-03-28 10:02:20 -07003376 GLsizei writeLength = 0;
3377
Geoff Langf41d0ee2016-10-07 13:04:23 -04003378 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003379 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3380 {
3381 return false;
3382 }
3383
3384 SetRobustLengthParam(length, writeLength);
3385
3386 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003387}
3388
3389bool ValidateGetUniformivRobustANGLE(Context *context,
3390 GLuint program,
3391 GLint location,
3392 GLsizei bufSize,
3393 GLsizei *length,
3394 GLint *params)
3395{
3396 if (!ValidateRobustEntryPoint(context, bufSize))
3397 {
3398 return false;
3399 }
3400
Brandon Jonesd1049182018-03-28 10:02:20 -07003401 GLsizei writeLength = 0;
3402
Geoff Langf41d0ee2016-10-07 13:04:23 -04003403 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003404 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3405 {
3406 return false;
3407 }
3408
3409 SetRobustLengthParam(length, writeLength);
3410
3411 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003412}
3413
3414bool ValidateGetUniformuivRobustANGLE(Context *context,
3415 GLuint program,
3416 GLint location,
3417 GLsizei bufSize,
3418 GLsizei *length,
3419 GLuint *params)
3420{
3421 if (!ValidateRobustEntryPoint(context, bufSize))
3422 {
3423 return false;
3424 }
3425
3426 if (context->getClientMajorVersion() < 3)
3427 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003428 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003429 return false;
3430 }
3431
Brandon Jonesd1049182018-03-28 10:02:20 -07003432 GLsizei writeLength = 0;
3433
Geoff Langf41d0ee2016-10-07 13:04:23 -04003434 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003435 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3436 {
3437 return false;
3438 }
3439
3440 SetRobustLengthParam(length, writeLength);
3441
3442 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003443}
3444
He Yunchaoced53ae2016-11-29 15:00:51 +08003445bool ValidateDiscardFramebufferBase(Context *context,
3446 GLenum target,
3447 GLsizei numAttachments,
3448 const GLenum *attachments,
3449 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003450{
3451 if (numAttachments < 0)
3452 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003453 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003454 return false;
3455 }
3456
3457 for (GLsizei i = 0; i < numAttachments; ++i)
3458 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003459 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003460 {
3461 if (defaultFramebuffer)
3462 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003463 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003464 return false;
3465 }
3466
3467 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003469 context->handleError(InvalidOperation() << "Requested color attachment is "
3470 "greater than the maximum supported "
3471 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003472 return false;
3473 }
3474 }
3475 else
3476 {
3477 switch (attachments[i])
3478 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003479 case GL_DEPTH_ATTACHMENT:
3480 case GL_STENCIL_ATTACHMENT:
3481 case GL_DEPTH_STENCIL_ATTACHMENT:
3482 if (defaultFramebuffer)
3483 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003484 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3485 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003486 return false;
3487 }
3488 break;
3489 case GL_COLOR:
3490 case GL_DEPTH:
3491 case GL_STENCIL:
3492 if (!defaultFramebuffer)
3493 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003494 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3495 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003496 return false;
3497 }
3498 break;
3499 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003500 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003501 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003502 }
3503 }
3504 }
3505
3506 return true;
3507}
3508
Austin Kinross6ee1e782015-05-29 17:05:37 -07003509bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3510{
Jamie Madill007530e2017-12-28 14:27:04 -05003511 if (!context->getExtensions().debugMarker)
3512 {
3513 // The debug marker calls should not set error state
3514 // However, it seems reasonable to set an error state if the extension is not enabled
3515 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3516 return false;
3517 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003518
Jamie Madill007530e2017-12-28 14:27:04 -05003519 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003520 if (length < 0)
3521 {
3522 return false;
3523 }
3524
3525 if (marker == nullptr)
3526 {
3527 return false;
3528 }
3529
3530 return true;
3531}
3532
3533bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3534{
Jamie Madill007530e2017-12-28 14:27:04 -05003535 if (!context->getExtensions().debugMarker)
3536 {
3537 // The debug marker calls should not set error state
3538 // However, it seems reasonable to set an error state if the extension is not enabled
3539 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3540 return false;
3541 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003542
Jamie Madill007530e2017-12-28 14:27:04 -05003543 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003544 if (length < 0)
3545 {
3546 return false;
3547 }
3548
3549 if (length > 0 && marker == nullptr)
3550 {
3551 return false;
3552 }
3553
3554 return true;
3555}
3556
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003557bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003558{
Geoff Langa8406172015-07-21 16:53:39 -04003559 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003561 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003562 return false;
3563 }
3564
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003565 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003566 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003567 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003568 if (!context->getExtensions().eglImage)
3569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003570 context->handleError(InvalidEnum()
3571 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003572 }
3573 break;
3574
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003575 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003576 if (!context->getExtensions().eglImageExternal)
3577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003578 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3579 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003580 }
Geoff Langa8406172015-07-21 16:53:39 -04003581 break;
3582
3583 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003584 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003585 return false;
3586 }
3587
Rafael Cintron05a449a2018-06-20 18:08:04 -07003588 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003589
Jamie Madill61e16b42017-06-19 11:13:23 -04003590 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003591 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003593 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003594 return false;
3595 }
3596
Jamie Madill007530e2017-12-28 14:27:04 -05003597 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003599 context->handleError(InvalidOperation()
3600 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003601 return false;
3602 }
3603
Geoff Langca271392017-04-05 12:30:00 -04003604 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003605 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003606 if (!textureCaps.texturable)
3607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003608 context->handleError(InvalidOperation()
3609 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003610 return false;
3611 }
3612
Geoff Langdcab33b2015-07-21 13:03:16 -04003613 return true;
3614}
3615
3616bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003617 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003618 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003619{
Geoff Langa8406172015-07-21 16:53:39 -04003620 if (!context->getExtensions().eglImage)
3621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003622 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003623 return false;
3624 }
3625
3626 switch (target)
3627 {
3628 case GL_RENDERBUFFER:
3629 break;
3630
3631 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003632 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003633 return false;
3634 }
3635
Rafael Cintron05a449a2018-06-20 18:08:04 -07003636 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003637
Jamie Madill61e16b42017-06-19 11:13:23 -04003638 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003639 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003641 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003642 return false;
3643 }
3644
Geoff Langca271392017-04-05 12:30:00 -04003645 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003646 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003647 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003648 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003649 context->handleError(InvalidOperation()
3650 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003651 return false;
3652 }
3653
Geoff Langdcab33b2015-07-21 13:03:16 -04003654 return true;
3655}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003656
3657bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3658{
Geoff Lang36167ab2015-12-07 10:27:14 -05003659 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003660 {
3661 // The default VAO should always exist
3662 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003663 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003664 return false;
3665 }
3666
3667 return true;
3668}
3669
Geoff Langc5629752015-12-07 16:29:04 -05003670bool ValidateProgramBinaryBase(Context *context,
3671 GLuint program,
3672 GLenum binaryFormat,
3673 const void *binary,
3674 GLint length)
3675{
3676 Program *programObject = GetValidProgram(context, program);
3677 if (programObject == nullptr)
3678 {
3679 return false;
3680 }
3681
3682 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3683 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3684 programBinaryFormats.end())
3685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003686 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003687 return false;
3688 }
3689
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003690 if (context->hasActiveTransformFeedback(program))
3691 {
3692 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003693 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3694 "is associated with an active transform "
3695 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003696 return false;
3697 }
3698
Geoff Langc5629752015-12-07 16:29:04 -05003699 return true;
3700}
3701
3702bool ValidateGetProgramBinaryBase(Context *context,
3703 GLuint program,
3704 GLsizei bufSize,
3705 GLsizei *length,
3706 GLenum *binaryFormat,
3707 void *binary)
3708{
3709 Program *programObject = GetValidProgram(context, program);
3710 if (programObject == nullptr)
3711 {
3712 return false;
3713 }
3714
3715 if (!programObject->isLinked())
3716 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003717 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003718 return false;
3719 }
3720
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003721 if (context->getCaps().programBinaryFormats.empty())
3722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003723 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003724 return false;
3725 }
3726
Geoff Langc5629752015-12-07 16:29:04 -05003727 return true;
3728}
Jamie Madillc29968b2016-01-20 11:17:23 -05003729
Jamie Madill5b772312018-03-08 20:28:32 -05003730bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003731{
3732 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003733 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003734 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003735 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3736 return false;
3737 }
3738 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3739 {
3740 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003741 return false;
3742 }
3743
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003744 ASSERT(context->getGLState().getDrawFramebuffer());
3745 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003746 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3747
3748 // This should come first before the check for the default frame buffer
3749 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3750 // rather than INVALID_OPERATION
3751 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3752 {
3753 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3754
3755 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003756 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3757 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003758 {
3759 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003760 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3761 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3762 // 3.1 is still a bit ambiguous about the error, but future specs are
3763 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003764 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003765 return false;
3766 }
3767 else if (bufs[colorAttachment] >= maxColorAttachment)
3768 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003769 context->handleError(InvalidOperation()
3770 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003771 return false;
3772 }
3773 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3774 frameBufferId != 0)
3775 {
3776 // INVALID_OPERATION-GL is bound to buffer and ith argument
3777 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidOperation()
3779 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003780 return false;
3781 }
3782 }
3783
3784 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3785 // and n is not 1 or bufs is bound to value other than BACK and NONE
3786 if (frameBufferId == 0)
3787 {
3788 if (n != 1)
3789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003790 context->handleError(InvalidOperation()
3791 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003792 return false;
3793 }
3794
3795 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003797 context->handleError(
3798 InvalidOperation()
3799 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003800 return false;
3801 }
3802 }
3803
3804 return true;
3805}
3806
Geoff Lang496c02d2016-10-20 11:38:11 -07003807bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003808 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003809 GLenum pname,
3810 GLsizei *length,
3811 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003812{
Geoff Lang496c02d2016-10-20 11:38:11 -07003813 if (length)
3814 {
3815 *length = 0;
3816 }
3817
3818 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3819 {
3820 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003821 InvalidOperation()
3822 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003823 return false;
3824 }
3825
Corentin Walleze4477002017-12-01 14:39:58 -05003826 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003827 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003828 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003829 return false;
3830 }
3831
Geoff Lang496c02d2016-10-20 11:38:11 -07003832 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003833 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003834 case GL_BUFFER_MAP_POINTER:
3835 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003836
Geoff Lang496c02d2016-10-20 11:38:11 -07003837 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003838 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003839 return false;
3840 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003841
3842 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3843 // target bound to zero generate an INVALID_OPERATION error."
3844 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003845 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003847 context->handleError(InvalidOperation()
3848 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003849 return false;
3850 }
3851
Geoff Lang496c02d2016-10-20 11:38:11 -07003852 if (length)
3853 {
3854 *length = 1;
3855 }
3856
Olli Etuaho4f667482016-03-30 15:56:35 +03003857 return true;
3858}
3859
Corentin Wallez336129f2017-10-17 15:55:40 -04003860bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003861{
Corentin Walleze4477002017-12-01 14:39:58 -05003862 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003864 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003865 return false;
3866 }
3867
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003868 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003869
3870 if (buffer == nullptr || !buffer->isMapped())
3871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003872 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003873 return false;
3874 }
3875
3876 return true;
3877}
3878
3879bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003880 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003881 GLintptr offset,
3882 GLsizeiptr length,
3883 GLbitfield access)
3884{
Corentin Walleze4477002017-12-01 14:39:58 -05003885 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003886 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003888 return false;
3889 }
3890
Brandon Jones6cad5662017-06-14 13:25:13 -07003891 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003892 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003893 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3894 return false;
3895 }
3896
3897 if (length < 0)
3898 {
3899 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 return false;
3901 }
3902
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003903 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003904
3905 if (!buffer)
3906 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003907 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 return false;
3909 }
3910
3911 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003912 CheckedNumeric<size_t> checkedOffset(offset);
3913 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003914
Jamie Madille2e406c2016-06-02 13:04:10 -04003915 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003917 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003918 return false;
3919 }
3920
3921 // Check for invalid bits in the mask
3922 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3923 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3924 GL_MAP_UNSYNCHRONIZED_BIT;
3925
3926 if (access & ~(allAccessBits))
3927 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003928 context->handleError(InvalidValue()
3929 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003930 return false;
3931 }
3932
3933 if (length == 0)
3934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003935 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003936 return false;
3937 }
3938
3939 if (buffer->isMapped())
3940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003941 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003942 return false;
3943 }
3944
3945 // Check for invalid bit combinations
3946 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003948 context->handleError(InvalidOperation()
3949 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003950 return false;
3951 }
3952
3953 GLbitfield writeOnlyBits =
3954 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3955
3956 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003958 context->handleError(InvalidOperation()
3959 << "Invalid access bits when mapping buffer for reading: 0x"
3960 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003961 return false;
3962 }
3963
3964 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003966 context->handleError(
3967 InvalidOperation()
3968 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003969 return false;
3970 }
Geoff Lang79f71042017-08-14 16:43:43 -04003971
3972 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003973}
3974
3975bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003976 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003977 GLintptr offset,
3978 GLsizeiptr length)
3979{
Brandon Jones6cad5662017-06-14 13:25:13 -07003980 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003981 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003982 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3983 return false;
3984 }
3985
3986 if (length < 0)
3987 {
3988 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003989 return false;
3990 }
3991
Corentin Walleze4477002017-12-01 14:39:58 -05003992 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003993 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003994 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003995 return false;
3996 }
3997
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003998 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003999
4000 if (buffer == nullptr)
4001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004002 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004003 return false;
4004 }
4005
4006 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004008 context->handleError(InvalidOperation()
4009 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004010 return false;
4011 }
4012
4013 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004014 CheckedNumeric<size_t> checkedOffset(offset);
4015 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004016
Jamie Madille2e406c2016-06-02 13:04:10 -04004017 if (!checkedSize.IsValid() ||
4018 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004020 context->handleError(InvalidValue()
4021 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004022 return false;
4023 }
4024
4025 return true;
4026}
4027
Olli Etuaho41997e72016-03-10 13:38:39 +02004028bool ValidateGenOrDelete(Context *context, GLint n)
4029{
4030 if (n < 0)
4031 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004032 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004033 return false;
4034 }
4035 return true;
4036}
4037
Jamie Madill5b772312018-03-08 20:28:32 -05004038bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004039{
4040 if (!context->getExtensions().robustClientMemory)
4041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004042 context->handleError(InvalidOperation()
4043 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004044 return false;
4045 }
4046
4047 if (bufSize < 0)
4048 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004049 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004050 return false;
4051 }
4052
4053 return true;
4054}
4055
Jamie Madill5b772312018-03-08 20:28:32 -05004056bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004057{
4058 if (bufSize < numParams)
4059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004060 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4061 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004062 return false;
4063 }
4064
4065 return true;
4066}
4067
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004068bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004069 GLenum target,
4070 GLenum attachment,
4071 GLenum pname,
4072 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004073{
Geoff Lange8afa902017-09-27 15:00:43 -04004074 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004076 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 return false;
4078 }
4079
4080 int clientVersion = context->getClientMajorVersion();
4081
4082 switch (pname)
4083 {
4084 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4085 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4086 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4087 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4088 break;
4089
Martin Radeve5285d22017-07-14 16:23:53 +03004090 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4091 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4092 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4093 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4094 if (clientVersion < 3 || !context->getExtensions().multiview)
4095 {
4096 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4097 return false;
4098 }
4099 break;
4100
Geoff Langff5b2d52016-09-07 11:32:23 -04004101 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4102 if (clientVersion < 3 && !context->getExtensions().sRGB)
4103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004104 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004105 return false;
4106 }
4107 break;
4108
4109 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4110 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4111 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4112 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4113 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4114 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4115 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4116 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4117 if (clientVersion < 3)
4118 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004119 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004120 return false;
4121 }
4122 break;
4123
Jiawei Shaoa8802472018-05-28 11:17:47 +08004124 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4125 if (!context->getExtensions().geometryShader)
4126 {
4127 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4128 return false;
4129 }
4130 break;
4131
Geoff Langff5b2d52016-09-07 11:32:23 -04004132 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004133 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004134 return false;
4135 }
4136
4137 // Determine if the attachment is a valid enum
4138 switch (attachment)
4139 {
4140 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004141 case GL_DEPTH:
4142 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004143 if (clientVersion < 3)
4144 {
Geoff Langfa125c92017-10-24 13:01:46 -04004145 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 return false;
4147 }
4148 break;
4149
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004150 case GL_DEPTH_STENCIL_ATTACHMENT:
4151 if (clientVersion < 3 && !context->isWebGL1())
4152 {
4153 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4154 return false;
4155 }
4156 break;
4157
Geoff Langfa125c92017-10-24 13:01:46 -04004158 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 case GL_DEPTH_ATTACHMENT:
4160 case GL_STENCIL_ATTACHMENT:
4161 break;
4162
4163 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004164 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4165 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4167 {
Geoff Langfa125c92017-10-24 13:01:46 -04004168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004169 return false;
4170 }
4171 break;
4172 }
4173
4174 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4175 ASSERT(framebuffer);
4176
4177 if (framebuffer->id() == 0)
4178 {
4179 if (clientVersion < 3)
4180 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004181 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004182 return false;
4183 }
4184
4185 switch (attachment)
4186 {
4187 case GL_BACK:
4188 case GL_DEPTH:
4189 case GL_STENCIL:
4190 break;
4191
4192 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004194 return false;
4195 }
4196 }
4197 else
4198 {
4199 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4200 {
4201 // Valid attachment query
4202 }
4203 else
4204 {
4205 switch (attachment)
4206 {
4207 case GL_DEPTH_ATTACHMENT:
4208 case GL_STENCIL_ATTACHMENT:
4209 break;
4210
4211 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004212 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004214 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004215 return false;
4216 }
4217 break;
4218
4219 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004220 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004221 return false;
4222 }
4223 }
4224 }
4225
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004226 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004227 if (attachmentObject)
4228 {
4229 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4230 attachmentObject->type() == GL_TEXTURE ||
4231 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4232
4233 switch (pname)
4234 {
4235 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4236 if (attachmentObject->type() != GL_RENDERBUFFER &&
4237 attachmentObject->type() != GL_TEXTURE)
4238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004239 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004240 return false;
4241 }
4242 break;
4243
4244 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4245 if (attachmentObject->type() != GL_TEXTURE)
4246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004247 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004248 return false;
4249 }
4250 break;
4251
4252 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4253 if (attachmentObject->type() != GL_TEXTURE)
4254 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004256 return false;
4257 }
4258 break;
4259
4260 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4261 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4262 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004264 return false;
4265 }
4266 break;
4267
4268 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4269 if (attachmentObject->type() != GL_TEXTURE)
4270 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004271 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004272 return false;
4273 }
4274 break;
4275
4276 default:
4277 break;
4278 }
4279 }
4280 else
4281 {
4282 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4283 // is NONE, then querying any other pname will generate INVALID_ENUM.
4284
4285 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4286 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4287 // INVALID_OPERATION for all other pnames
4288
4289 switch (pname)
4290 {
4291 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4292 break;
4293
4294 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4295 if (clientVersion < 3)
4296 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004297 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004298 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004299 return false;
4300 }
4301 break;
4302
4303 default:
4304 if (clientVersion < 3)
4305 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004306 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004307 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004308 return false;
4309 }
4310 else
4311 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004312 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004313 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004314 return false;
4315 }
4316 }
4317 }
4318
Martin Radeve5285d22017-07-14 16:23:53 +03004319 if (numParams)
4320 {
4321 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4322 {
4323 // Only when the viewport offsets are queried we can have a varying number of output
4324 // parameters.
4325 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4326 *numParams = numViews * 2;
4327 }
4328 else
4329 {
4330 // For all other queries we can have only one output parameter.
4331 *numParams = 1;
4332 }
4333 }
4334
Geoff Langff5b2d52016-09-07 11:32:23 -04004335 return true;
4336}
4337
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004338bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004339 GLenum target,
4340 GLenum attachment,
4341 GLenum pname,
4342 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004343 GLsizei *length,
4344 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004345{
4346 if (!ValidateRobustEntryPoint(context, bufSize))
4347 {
4348 return false;
4349 }
4350
Brandon Jonesd1049182018-03-28 10:02:20 -07004351 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004352 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004353 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004354 {
4355 return false;
4356 }
4357
Brandon Jonesd1049182018-03-28 10:02:20 -07004358 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004359 {
4360 return false;
4361 }
4362
Brandon Jonesd1049182018-03-28 10:02:20 -07004363 SetRobustLengthParam(length, numParams);
4364
Geoff Langff5b2d52016-09-07 11:32:23 -04004365 return true;
4366}
4367
Jamie Madill5b772312018-03-08 20:28:32 -05004368bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004369 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004370 GLenum pname,
4371 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004372 GLsizei *length,
4373 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004374{
4375 if (!ValidateRobustEntryPoint(context, bufSize))
4376 {
4377 return false;
4378 }
4379
Brandon Jonesd1049182018-03-28 10:02:20 -07004380 GLsizei numParams = 0;
4381
4382 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004383 {
4384 return false;
4385 }
4386
Brandon Jonesd1049182018-03-28 10:02:20 -07004387 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004388 {
4389 return false;
4390 }
4391
Brandon Jonesd1049182018-03-28 10:02:20 -07004392 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004393 return true;
4394}
4395
Jamie Madill5b772312018-03-08 20:28:32 -05004396bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004397 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004398 GLenum pname,
4399 GLsizei bufSize,
4400 GLsizei *length,
4401 GLint64 *params)
4402{
Brandon Jonesd1049182018-03-28 10:02:20 -07004403 GLsizei numParams = 0;
4404
Geoff Langebebe1c2016-10-14 12:01:31 -04004405 if (!ValidateRobustEntryPoint(context, bufSize))
4406 {
4407 return false;
4408 }
4409
Brandon Jonesd1049182018-03-28 10:02:20 -07004410 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004411 {
4412 return false;
4413 }
4414
Brandon Jonesd1049182018-03-28 10:02:20 -07004415 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004416 {
4417 return false;
4418 }
4419
Brandon Jonesd1049182018-03-28 10:02:20 -07004420 SetRobustLengthParam(length, numParams);
4421
Geoff Langff5b2d52016-09-07 11:32:23 -04004422 return true;
4423}
4424
Jamie Madill5b772312018-03-08 20:28:32 -05004425bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004426{
4427 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004428 if (numParams)
4429 {
4430 *numParams = 1;
4431 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004432
4433 Program *programObject = GetValidProgram(context, program);
4434 if (!programObject)
4435 {
4436 return false;
4437 }
4438
4439 switch (pname)
4440 {
4441 case GL_DELETE_STATUS:
4442 case GL_LINK_STATUS:
4443 case GL_VALIDATE_STATUS:
4444 case GL_INFO_LOG_LENGTH:
4445 case GL_ATTACHED_SHADERS:
4446 case GL_ACTIVE_ATTRIBUTES:
4447 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4448 case GL_ACTIVE_UNIFORMS:
4449 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4450 break;
4451
4452 case GL_PROGRAM_BINARY_LENGTH:
4453 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004455 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4456 "requires GL_OES_get_program_binary or "
4457 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004458 return false;
4459 }
4460 break;
4461
4462 case GL_ACTIVE_UNIFORM_BLOCKS:
4463 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4464 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4465 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4466 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4467 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4468 if (context->getClientMajorVersion() < 3)
4469 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004470 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004471 return false;
4472 }
4473 break;
4474
Yunchao He61afff12017-03-14 15:34:03 +08004475 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004476 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004477 if (context->getClientVersion() < Version(3, 1))
4478 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004479 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004480 return false;
4481 }
4482 break;
4483
Jiawei Shao6ae51612018-02-23 14:03:25 +08004484 case GL_COMPUTE_WORK_GROUP_SIZE:
4485 if (context->getClientVersion() < Version(3, 1))
4486 {
4487 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4488 return false;
4489 }
4490
4491 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4492 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4493 // program which has not been linked successfully, or which does not contain objects to
4494 // form a compute shader.
4495 if (!programObject->isLinked())
4496 {
4497 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4498 return false;
4499 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004500 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004501 {
4502 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4503 return false;
4504 }
4505 break;
4506
Jiawei Shao447bfac2018-03-14 14:23:40 +08004507 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4508 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4509 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4510 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4511 if (!context->getExtensions().geometryShader)
4512 {
4513 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4514 return false;
4515 }
4516
4517 // [EXT_geometry_shader] Chapter 7.12
4518 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4519 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4520 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4521 // successfully, or which does not contain objects to form a geometry shader.
4522 if (!programObject->isLinked())
4523 {
4524 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4525 return false;
4526 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004527 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004528 {
4529 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4530 return false;
4531 }
4532 break;
4533
Geoff Langff5b2d52016-09-07 11:32:23 -04004534 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004536 return false;
4537 }
4538
4539 return true;
4540}
4541
4542bool ValidateGetProgramivRobustANGLE(Context *context,
4543 GLuint program,
4544 GLenum pname,
4545 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004546 GLsizei *length,
4547 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004548{
4549 if (!ValidateRobustEntryPoint(context, bufSize))
4550 {
4551 return false;
4552 }
4553
Brandon Jonesd1049182018-03-28 10:02:20 -07004554 GLsizei numParams = 0;
4555
4556 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004557 {
4558 return false;
4559 }
4560
Brandon Jonesd1049182018-03-28 10:02:20 -07004561 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004562 {
4563 return false;
4564 }
4565
Brandon Jonesd1049182018-03-28 10:02:20 -07004566 SetRobustLengthParam(length, numParams);
4567
Geoff Langff5b2d52016-09-07 11:32:23 -04004568 return true;
4569}
4570
Geoff Lang740d9022016-10-07 11:20:52 -04004571bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4572 GLenum target,
4573 GLenum pname,
4574 GLsizei bufSize,
4575 GLsizei *length,
4576 GLint *params)
4577{
4578 if (!ValidateRobustEntryPoint(context, bufSize))
4579 {
4580 return false;
4581 }
4582
Brandon Jonesd1049182018-03-28 10:02:20 -07004583 GLsizei numParams = 0;
4584
4585 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004586 {
4587 return false;
4588 }
4589
Brandon Jonesd1049182018-03-28 10:02:20 -07004590 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004591 {
4592 return false;
4593 }
4594
Brandon Jonesd1049182018-03-28 10:02:20 -07004595 SetRobustLengthParam(length, numParams);
4596
Geoff Lang740d9022016-10-07 11:20:52 -04004597 return true;
4598}
4599
Geoff Langd7d0ed32016-10-07 11:33:51 -04004600bool ValidateGetShaderivRobustANGLE(Context *context,
4601 GLuint shader,
4602 GLenum pname,
4603 GLsizei bufSize,
4604 GLsizei *length,
4605 GLint *params)
4606{
4607 if (!ValidateRobustEntryPoint(context, bufSize))
4608 {
4609 return false;
4610 }
4611
Brandon Jonesd1049182018-03-28 10:02:20 -07004612 GLsizei numParams = 0;
4613
4614 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004615 {
4616 return false;
4617 }
4618
Brandon Jonesd1049182018-03-28 10:02:20 -07004619 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004620 {
4621 return false;
4622 }
4623
Brandon Jonesd1049182018-03-28 10:02:20 -07004624 SetRobustLengthParam(length, numParams);
4625
Geoff Langd7d0ed32016-10-07 11:33:51 -04004626 return true;
4627}
4628
Geoff Langc1984ed2016-10-07 12:41:00 -04004629bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004630 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004631 GLenum pname,
4632 GLsizei bufSize,
4633 GLsizei *length,
4634 GLfloat *params)
4635{
4636 if (!ValidateRobustEntryPoint(context, bufSize))
4637 {
4638 return false;
4639 }
4640
Brandon Jonesd1049182018-03-28 10:02:20 -07004641 GLsizei numParams = 0;
4642
4643 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004644 {
4645 return false;
4646 }
4647
Brandon Jonesd1049182018-03-28 10:02:20 -07004648 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004649 {
4650 return false;
4651 }
4652
Brandon Jonesd1049182018-03-28 10:02:20 -07004653 SetRobustLengthParam(length, numParams);
4654
Geoff Langc1984ed2016-10-07 12:41:00 -04004655 return true;
4656}
4657
Geoff Langc1984ed2016-10-07 12:41:00 -04004658bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004659 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004660 GLenum pname,
4661 GLsizei bufSize,
4662 GLsizei *length,
4663 GLint *params)
4664{
Brandon Jonesd1049182018-03-28 10:02:20 -07004665
Geoff Langc1984ed2016-10-07 12:41:00 -04004666 if (!ValidateRobustEntryPoint(context, bufSize))
4667 {
4668 return false;
4669 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004670 GLsizei numParams = 0;
4671 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004672 {
4673 return false;
4674 }
4675
Brandon Jonesd1049182018-03-28 10:02:20 -07004676 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004677 {
4678 return false;
4679 }
4680
Brandon Jonesd1049182018-03-28 10:02:20 -07004681 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004682 return true;
4683}
4684
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004685bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4686 TextureType target,
4687 GLenum pname,
4688 GLsizei bufSize,
4689 GLsizei *length,
4690 GLint *params)
4691{
4692 UNIMPLEMENTED();
4693 return false;
4694}
4695
4696bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4697 TextureType target,
4698 GLenum pname,
4699 GLsizei bufSize,
4700 GLsizei *length,
4701 GLuint *params)
4702{
4703 UNIMPLEMENTED();
4704 return false;
4705}
4706
Geoff Langc1984ed2016-10-07 12:41:00 -04004707bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004708 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004709 GLenum pname,
4710 GLsizei bufSize,
4711 const GLfloat *params)
4712{
4713 if (!ValidateRobustEntryPoint(context, bufSize))
4714 {
4715 return false;
4716 }
4717
4718 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4719}
4720
Geoff Langc1984ed2016-10-07 12:41:00 -04004721bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004722 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004723 GLenum pname,
4724 GLsizei bufSize,
4725 const GLint *params)
4726{
4727 if (!ValidateRobustEntryPoint(context, bufSize))
4728 {
4729 return false;
4730 }
4731
4732 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4733}
4734
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004735bool ValidateTexParameterIivRobustANGLE(Context *context,
4736 TextureType target,
4737 GLenum pname,
4738 GLsizei bufSize,
4739 const GLint *params)
4740{
4741 UNIMPLEMENTED();
4742 return false;
4743}
4744
4745bool ValidateTexParameterIuivRobustANGLE(Context *context,
4746 TextureType target,
4747 GLenum pname,
4748 GLsizei bufSize,
4749 const GLuint *params)
4750{
4751 UNIMPLEMENTED();
4752 return false;
4753}
4754
Geoff Langc1984ed2016-10-07 12:41:00 -04004755bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4756 GLuint sampler,
4757 GLenum pname,
4758 GLuint bufSize,
4759 GLsizei *length,
4760 GLfloat *params)
4761{
4762 if (!ValidateRobustEntryPoint(context, bufSize))
4763 {
4764 return false;
4765 }
4766
Brandon Jonesd1049182018-03-28 10:02:20 -07004767 GLsizei numParams = 0;
4768
4769 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004770 {
4771 return false;
4772 }
4773
Brandon Jonesd1049182018-03-28 10:02:20 -07004774 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004775 {
4776 return false;
4777 }
4778
Brandon Jonesd1049182018-03-28 10:02:20 -07004779 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004780 return true;
4781}
4782
Geoff Langc1984ed2016-10-07 12:41:00 -04004783bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4784 GLuint sampler,
4785 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004786 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004787 GLsizei *length,
4788 GLint *params)
4789{
4790 if (!ValidateRobustEntryPoint(context, bufSize))
4791 {
4792 return false;
4793 }
4794
Brandon Jonesd1049182018-03-28 10:02:20 -07004795 GLsizei numParams = 0;
4796
4797 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004798 {
4799 return false;
4800 }
4801
Brandon Jonesd1049182018-03-28 10:02:20 -07004802 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004803 {
4804 return false;
4805 }
4806
Brandon Jonesd1049182018-03-28 10:02:20 -07004807 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004808 return true;
4809}
4810
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004811bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4812 GLuint sampler,
4813 GLenum pname,
4814 GLsizei bufSize,
4815 GLsizei *length,
4816 GLint *params)
4817{
4818 UNIMPLEMENTED();
4819 return false;
4820}
4821
4822bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4823 GLuint sampler,
4824 GLenum pname,
4825 GLsizei bufSize,
4826 GLsizei *length,
4827 GLuint *params)
4828{
4829 UNIMPLEMENTED();
4830 return false;
4831}
4832
Geoff Langc1984ed2016-10-07 12:41:00 -04004833bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4834 GLuint sampler,
4835 GLenum pname,
4836 GLsizei bufSize,
4837 const GLfloat *params)
4838{
4839 if (!ValidateRobustEntryPoint(context, bufSize))
4840 {
4841 return false;
4842 }
4843
4844 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4845}
4846
Geoff Langc1984ed2016-10-07 12:41:00 -04004847bool ValidateSamplerParameterivRobustANGLE(Context *context,
4848 GLuint sampler,
4849 GLenum pname,
4850 GLsizei bufSize,
4851 const GLint *params)
4852{
4853 if (!ValidateRobustEntryPoint(context, bufSize))
4854 {
4855 return false;
4856 }
4857
4858 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4859}
4860
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004861bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4862 GLuint sampler,
4863 GLenum pname,
4864 GLsizei bufSize,
4865 const GLint *param)
4866{
4867 UNIMPLEMENTED();
4868 return false;
4869}
4870
4871bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4872 GLuint sampler,
4873 GLenum pname,
4874 GLsizei bufSize,
4875 const GLuint *param)
4876{
4877 UNIMPLEMENTED();
4878 return false;
4879}
4880
Geoff Lang0b031062016-10-13 14:30:04 -04004881bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4882 GLuint index,
4883 GLenum pname,
4884 GLsizei bufSize,
4885 GLsizei *length,
4886 GLfloat *params)
4887{
4888 if (!ValidateRobustEntryPoint(context, bufSize))
4889 {
4890 return false;
4891 }
4892
Brandon Jonesd1049182018-03-28 10:02:20 -07004893 GLsizei writeLength = 0;
4894
4895 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004896 {
4897 return false;
4898 }
4899
Brandon Jonesd1049182018-03-28 10:02:20 -07004900 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004901 {
4902 return false;
4903 }
4904
Brandon Jonesd1049182018-03-28 10:02:20 -07004905 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004906 return true;
4907}
4908
Geoff Lang0b031062016-10-13 14:30:04 -04004909bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4910 GLuint index,
4911 GLenum pname,
4912 GLsizei bufSize,
4913 GLsizei *length,
4914 GLint *params)
4915{
4916 if (!ValidateRobustEntryPoint(context, bufSize))
4917 {
4918 return false;
4919 }
4920
Brandon Jonesd1049182018-03-28 10:02:20 -07004921 GLsizei writeLength = 0;
4922
4923 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004924 {
4925 return false;
4926 }
4927
Brandon Jonesd1049182018-03-28 10:02:20 -07004928 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004929 {
4930 return false;
4931 }
4932
Brandon Jonesd1049182018-03-28 10:02:20 -07004933 SetRobustLengthParam(length, writeLength);
4934
Geoff Lang0b031062016-10-13 14:30:04 -04004935 return true;
4936}
4937
Geoff Lang0b031062016-10-13 14:30:04 -04004938bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4939 GLuint index,
4940 GLenum pname,
4941 GLsizei bufSize,
4942 GLsizei *length,
4943 void **pointer)
4944{
4945 if (!ValidateRobustEntryPoint(context, bufSize))
4946 {
4947 return false;
4948 }
4949
Brandon Jonesd1049182018-03-28 10:02:20 -07004950 GLsizei writeLength = 0;
4951
4952 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004953 {
4954 return false;
4955 }
4956
Brandon Jonesd1049182018-03-28 10:02:20 -07004957 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004958 {
4959 return false;
4960 }
4961
Brandon Jonesd1049182018-03-28 10:02:20 -07004962 SetRobustLengthParam(length, writeLength);
4963
Geoff Lang0b031062016-10-13 14:30:04 -04004964 return true;
4965}
4966
Geoff Lang0b031062016-10-13 14:30:04 -04004967bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4968 GLuint index,
4969 GLenum pname,
4970 GLsizei bufSize,
4971 GLsizei *length,
4972 GLint *params)
4973{
4974 if (!ValidateRobustEntryPoint(context, bufSize))
4975 {
4976 return false;
4977 }
4978
Brandon Jonesd1049182018-03-28 10:02:20 -07004979 GLsizei writeLength = 0;
4980
4981 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004982 {
4983 return false;
4984 }
4985
Brandon Jonesd1049182018-03-28 10:02:20 -07004986 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004987 {
4988 return false;
4989 }
4990
Brandon Jonesd1049182018-03-28 10:02:20 -07004991 SetRobustLengthParam(length, writeLength);
4992
Geoff Lang0b031062016-10-13 14:30:04 -04004993 return true;
4994}
4995
Geoff Lang0b031062016-10-13 14:30:04 -04004996bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4997 GLuint index,
4998 GLenum pname,
4999 GLsizei bufSize,
5000 GLsizei *length,
5001 GLuint *params)
5002{
5003 if (!ValidateRobustEntryPoint(context, bufSize))
5004 {
5005 return false;
5006 }
5007
Brandon Jonesd1049182018-03-28 10:02:20 -07005008 GLsizei writeLength = 0;
5009
5010 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005011 {
5012 return false;
5013 }
5014
Brandon Jonesd1049182018-03-28 10:02:20 -07005015 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005016 {
5017 return false;
5018 }
5019
Brandon Jonesd1049182018-03-28 10:02:20 -07005020 SetRobustLengthParam(length, writeLength);
5021
Geoff Lang0b031062016-10-13 14:30:04 -04005022 return true;
5023}
5024
Geoff Lang6899b872016-10-14 11:30:13 -04005025bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5026 GLuint program,
5027 GLuint uniformBlockIndex,
5028 GLenum pname,
5029 GLsizei bufSize,
5030 GLsizei *length,
5031 GLint *params)
5032{
5033 if (!ValidateRobustEntryPoint(context, bufSize))
5034 {
5035 return false;
5036 }
5037
Brandon Jonesd1049182018-03-28 10:02:20 -07005038 GLsizei writeLength = 0;
5039
5040 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5041 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005042 {
5043 return false;
5044 }
5045
Brandon Jonesd1049182018-03-28 10:02:20 -07005046 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005047 {
5048 return false;
5049 }
5050
Brandon Jonesd1049182018-03-28 10:02:20 -07005051 SetRobustLengthParam(length, writeLength);
5052
Geoff Lang6899b872016-10-14 11:30:13 -04005053 return true;
5054}
5055
Brandon Jones416aaf92018-04-10 08:10:16 -07005056bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005057 GLenum target,
5058 GLenum internalformat,
5059 GLenum pname,
5060 GLsizei bufSize,
5061 GLsizei *length,
5062 GLint *params)
5063{
5064 if (!ValidateRobustEntryPoint(context, bufSize))
5065 {
5066 return false;
5067 }
5068
Brandon Jonesd1049182018-03-28 10:02:20 -07005069 GLsizei numParams = 0;
5070
5071 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5072 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005073 {
5074 return false;
5075 }
5076
Brandon Jonesd1049182018-03-28 10:02:20 -07005077 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005078 {
5079 return false;
5080 }
5081
Brandon Jonesd1049182018-03-28 10:02:20 -07005082 SetRobustLengthParam(length, numParams);
5083
Geoff Lang0a9661f2016-10-20 10:59:20 -07005084 return true;
5085}
5086
Jamie Madill5b772312018-03-08 20:28:32 -05005087bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005088 GLuint attribIndex,
5089 GLint size,
5090 GLenum type,
5091 GLboolean pureInteger)
5092{
5093 const Caps &caps = context->getCaps();
5094 if (attribIndex >= caps.maxVertexAttributes)
5095 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005096 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005097 return false;
5098 }
5099
5100 if (size < 1 || size > 4)
5101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005102 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005103 return false;
Shao80957d92017-02-20 21:25:59 +08005104 }
5105
5106 switch (type)
5107 {
5108 case GL_BYTE:
5109 case GL_UNSIGNED_BYTE:
5110 case GL_SHORT:
5111 case GL_UNSIGNED_SHORT:
5112 break;
5113
5114 case GL_INT:
5115 case GL_UNSIGNED_INT:
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 break;
5123
5124 case GL_FIXED:
5125 case GL_FLOAT:
5126 if (pureInteger)
5127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005129 return false;
5130 }
5131 break;
5132
5133 case GL_HALF_FLOAT:
5134 if (context->getClientMajorVersion() < 3)
5135 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005136 context->handleError(InvalidEnum()
5137 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005138 return false;
5139 }
5140 if (pureInteger)
5141 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005142 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005143 return false;
5144 }
5145 break;
5146
5147 case GL_INT_2_10_10_10_REV:
5148 case GL_UNSIGNED_INT_2_10_10_10_REV:
5149 if (context->getClientMajorVersion() < 3)
5150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005151 context->handleError(InvalidEnum()
5152 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005153 return false;
5154 }
5155 if (pureInteger)
5156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005157 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005158 return false;
5159 }
5160 if (size != 4)
5161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005162 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5163 "UNSIGNED_INT_2_10_10_10_REV and "
5164 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005165 return false;
5166 }
5167 break;
5168
5169 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005170 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005171 return false;
5172 }
5173
5174 return true;
5175}
5176
Geoff Lang76e65652017-03-27 14:58:02 -04005177// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5178// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5179// specified clear value and the type of a buffer that is being cleared generates an
5180// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005181bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005182 GLint drawbuffer,
5183 const GLenum *validComponentTypes,
5184 size_t validComponentTypeCount)
5185{
5186 const FramebufferAttachment *attachment =
5187 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5188 if (attachment)
5189 {
5190 GLenum componentType = attachment->getFormat().info->componentType;
5191 const GLenum *end = validComponentTypes + validComponentTypeCount;
5192 if (std::find(validComponentTypes, end, componentType) == end)
5193 {
5194 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005195 InvalidOperation()
5196 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005197 return false;
5198 }
5199 }
5200
5201 return true;
5202}
5203
Jamie Madill5b772312018-03-08 20:28:32 -05005204bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005205{
5206 if (!ValidateRobustEntryPoint(context, dataSize))
5207 {
5208 return false;
5209 }
5210
Corentin Wallez336129f2017-10-17 15:55:40 -04005211 gl::Buffer *pixelUnpackBuffer =
5212 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005213 if (pixelUnpackBuffer == nullptr)
5214 {
5215 if (dataSize < imageSize)
5216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005217 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005218 }
5219 }
5220 return true;
5221}
5222
Jamie Madill5b772312018-03-08 20:28:32 -05005223bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005224 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005225 GLenum pname,
5226 bool pointerVersion,
5227 GLsizei *numParams)
5228{
5229 if (numParams)
5230 {
5231 *numParams = 0;
5232 }
5233
Corentin Walleze4477002017-12-01 14:39:58 -05005234 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005235 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005236 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005237 return false;
5238 }
5239
5240 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5241 if (!buffer)
5242 {
5243 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 return false;
5246 }
5247
5248 const Extensions &extensions = context->getExtensions();
5249
5250 switch (pname)
5251 {
5252 case GL_BUFFER_USAGE:
5253 case GL_BUFFER_SIZE:
5254 break;
5255
5256 case GL_BUFFER_ACCESS_OES:
5257 if (!extensions.mapBuffer)
5258 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005259 context->handleError(InvalidEnum()
5260 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005261 return false;
5262 }
5263 break;
5264
5265 case GL_BUFFER_MAPPED:
5266 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5267 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5268 !extensions.mapBufferRange)
5269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005270 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5271 "GL_OES_mapbuffer or "
5272 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005273 return false;
5274 }
5275 break;
5276
5277 case GL_BUFFER_MAP_POINTER:
5278 if (!pointerVersion)
5279 {
5280 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005281 InvalidEnum()
5282 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005283 return false;
5284 }
5285 break;
5286
5287 case GL_BUFFER_ACCESS_FLAGS:
5288 case GL_BUFFER_MAP_OFFSET:
5289 case GL_BUFFER_MAP_LENGTH:
5290 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005292 context->handleError(InvalidEnum()
5293 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005294 return false;
5295 }
5296 break;
5297
5298 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005300 return false;
5301 }
5302
5303 // All buffer parameter queries return one value.
5304 if (numParams)
5305 {
5306 *numParams = 1;
5307 }
5308
5309 return true;
5310}
5311
5312bool ValidateGetRenderbufferParameterivBase(Context *context,
5313 GLenum target,
5314 GLenum pname,
5315 GLsizei *length)
5316{
5317 if (length)
5318 {
5319 *length = 0;
5320 }
5321
5322 if (target != GL_RENDERBUFFER)
5323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005324 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 return false;
5326 }
5327
5328 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5329 if (renderbuffer == nullptr)
5330 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005331 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005332 return false;
5333 }
5334
5335 switch (pname)
5336 {
5337 case GL_RENDERBUFFER_WIDTH:
5338 case GL_RENDERBUFFER_HEIGHT:
5339 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5340 case GL_RENDERBUFFER_RED_SIZE:
5341 case GL_RENDERBUFFER_GREEN_SIZE:
5342 case GL_RENDERBUFFER_BLUE_SIZE:
5343 case GL_RENDERBUFFER_ALPHA_SIZE:
5344 case GL_RENDERBUFFER_DEPTH_SIZE:
5345 case GL_RENDERBUFFER_STENCIL_SIZE:
5346 break;
5347
5348 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5349 if (!context->getExtensions().framebufferMultisample)
5350 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005351 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005352 return false;
5353 }
5354 break;
5355
5356 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005358 return false;
5359 }
5360
5361 if (length)
5362 {
5363 *length = 1;
5364 }
5365 return true;
5366}
5367
5368bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5369{
5370 if (length)
5371 {
5372 *length = 0;
5373 }
5374
5375 if (GetValidShader(context, shader) == nullptr)
5376 {
5377 return false;
5378 }
5379
5380 switch (pname)
5381 {
5382 case GL_SHADER_TYPE:
5383 case GL_DELETE_STATUS:
5384 case GL_COMPILE_STATUS:
5385 case GL_INFO_LOG_LENGTH:
5386 case GL_SHADER_SOURCE_LENGTH:
5387 break;
5388
5389 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5390 if (!context->getExtensions().translatedShaderSource)
5391 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395 break;
5396
5397 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005399 return false;
5400 }
5401
5402 if (length)
5403 {
5404 *length = 1;
5405 }
5406 return true;
5407}
5408
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005409bool ValidateGetTexParameterBase(Context *context,
5410 TextureType target,
5411 GLenum pname,
5412 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005413{
5414 if (length)
5415 {
5416 *length = 0;
5417 }
5418
5419 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5420 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005422 return false;
5423 }
5424
5425 if (context->getTargetTexture(target) == nullptr)
5426 {
5427 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005429 return false;
5430 }
5431
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005432 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5433 {
5434 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5435 return false;
5436 }
5437
Jamie Madillbe849e42017-05-02 15:49:00 -04005438 switch (pname)
5439 {
5440 case GL_TEXTURE_MAG_FILTER:
5441 case GL_TEXTURE_MIN_FILTER:
5442 case GL_TEXTURE_WRAP_S:
5443 case GL_TEXTURE_WRAP_T:
5444 break;
5445
5446 case GL_TEXTURE_USAGE_ANGLE:
5447 if (!context->getExtensions().textureUsage)
5448 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005450 return false;
5451 }
5452 break;
5453
5454 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005455 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005456 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005457 return false;
5458 }
5459 break;
5460
5461 case GL_TEXTURE_IMMUTABLE_FORMAT:
5462 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5463 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005464 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005465 return false;
5466 }
5467 break;
5468
5469 case GL_TEXTURE_WRAP_R:
5470 case GL_TEXTURE_IMMUTABLE_LEVELS:
5471 case GL_TEXTURE_SWIZZLE_R:
5472 case GL_TEXTURE_SWIZZLE_G:
5473 case GL_TEXTURE_SWIZZLE_B:
5474 case GL_TEXTURE_SWIZZLE_A:
5475 case GL_TEXTURE_BASE_LEVEL:
5476 case GL_TEXTURE_MAX_LEVEL:
5477 case GL_TEXTURE_MIN_LOD:
5478 case GL_TEXTURE_MAX_LOD:
5479 case GL_TEXTURE_COMPARE_MODE:
5480 case GL_TEXTURE_COMPARE_FUNC:
5481 if (context->getClientMajorVersion() < 3)
5482 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005483 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486 break;
5487
5488 case GL_TEXTURE_SRGB_DECODE_EXT:
5489 if (!context->getExtensions().textureSRGBDecode)
5490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005491 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 return false;
5493 }
5494 break;
5495
Yunchao Hebacaa712018-01-30 14:01:39 +08005496 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5497 if (context->getClientVersion() < Version(3, 1))
5498 {
5499 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5500 return false;
5501 }
5502 break;
5503
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005504 case GL_GENERATE_MIPMAP:
5505 case GL_TEXTURE_CROP_RECT_OES:
5506 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5507 // after GL_OES_draw_texture functionality implemented
5508 if (context->getClientMajorVersion() > 1)
5509 {
5510 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5511 return false;
5512 }
5513 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005514 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005515 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005516 return false;
5517 }
5518
5519 if (length)
5520 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005521 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005522 }
5523 return true;
5524}
5525
5526bool ValidateGetVertexAttribBase(Context *context,
5527 GLuint index,
5528 GLenum pname,
5529 GLsizei *length,
5530 bool pointer,
5531 bool pureIntegerEntryPoint)
5532{
5533 if (length)
5534 {
5535 *length = 0;
5536 }
5537
5538 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005540 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005541 return false;
5542 }
5543
5544 if (index >= context->getCaps().maxVertexAttributes)
5545 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005546 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005547 return false;
5548 }
5549
5550 if (pointer)
5551 {
5552 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5553 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005554 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005555 return false;
5556 }
5557 }
5558 else
5559 {
5560 switch (pname)
5561 {
5562 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5563 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5564 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5565 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5566 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5567 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5568 case GL_CURRENT_VERTEX_ATTRIB:
5569 break;
5570
5571 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5572 static_assert(
5573 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5574 "ANGLE extension enums not equal to GL enums.");
5575 if (context->getClientMajorVersion() < 3 &&
5576 !context->getExtensions().instancedArrays)
5577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005578 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5579 "requires OpenGL ES 3.0 or "
5580 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005581 return false;
5582 }
5583 break;
5584
5585 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5586 if (context->getClientMajorVersion() < 3)
5587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005588 context->handleError(
5589 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005590 return false;
5591 }
5592 break;
5593
5594 case GL_VERTEX_ATTRIB_BINDING:
5595 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5596 if (context->getClientVersion() < ES_3_1)
5597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005598 context->handleError(InvalidEnum()
5599 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005600 return false;
5601 }
5602 break;
5603
5604 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005605 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005606 return false;
5607 }
5608 }
5609
5610 if (length)
5611 {
5612 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5613 {
5614 *length = 4;
5615 }
5616 else
5617 {
5618 *length = 1;
5619 }
5620 }
5621
5622 return true;
5623}
5624
Jamie Madill4928b7c2017-06-20 12:57:39 -04005625bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005626 GLint x,
5627 GLint y,
5628 GLsizei width,
5629 GLsizei height,
5630 GLenum format,
5631 GLenum type,
5632 GLsizei bufSize,
5633 GLsizei *length,
5634 GLsizei *columns,
5635 GLsizei *rows,
5636 void *pixels)
5637{
5638 if (length != nullptr)
5639 {
5640 *length = 0;
5641 }
5642 if (rows != nullptr)
5643 {
5644 *rows = 0;
5645 }
5646 if (columns != nullptr)
5647 {
5648 *columns = 0;
5649 }
5650
5651 if (width < 0 || height < 0)
5652 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005653 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005654 return false;
5655 }
5656
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005657 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005658
Jamie Madill427064d2018-04-13 16:20:34 -04005659 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005661 return false;
5662 }
5663
Jamie Madille98b1b52018-03-08 09:47:23 -05005664 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005665 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005666 return false;
5667 }
5668
Jamie Madill690c8eb2018-03-12 15:20:03 -04005669 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005670 ASSERT(framebuffer);
5671
5672 if (framebuffer->getReadBufferState() == GL_NONE)
5673 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005675 return false;
5676 }
5677
5678 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5679 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5680 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5681 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5682 // situation is an application error that would lead to a crash in ANGLE.
5683 if (readBuffer == nullptr)
5684 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005685 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005686 return false;
5687 }
5688
Martin Radev28031682017-07-28 14:47:56 +03005689 // ANGLE_multiview, Revision 1:
5690 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005691 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5692 // in the current read framebuffer is more than one.
5693 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005694 {
5695 context->handleError(InvalidFramebufferOperation()
5696 << "Attempting to read from a multi-view framebuffer.");
5697 return false;
5698 }
5699
Geoff Lang280ba992017-04-18 16:30:58 -04005700 if (context->getExtensions().webglCompatibility)
5701 {
5702 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5703 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5704 // and type before validating the combination of format and type. However, the
5705 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5706 // verifies that GL_INVALID_OPERATION is generated.
5707 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5708 // dEQP/WebGL.
5709 if (!ValidReadPixelsFormatEnum(context, format))
5710 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005711 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005712 return false;
5713 }
5714
5715 if (!ValidReadPixelsTypeEnum(context, type))
5716 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005717 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005718 return false;
5719 }
5720 }
5721
Jamie Madill690c8eb2018-03-12 15:20:03 -04005722 GLenum currentFormat = GL_NONE;
5723 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5724
5725 GLenum currentType = GL_NONE;
5726 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5727
Jamie Madillbe849e42017-05-02 15:49:00 -04005728 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5729
5730 bool validFormatTypeCombination =
5731 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5732
5733 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5734 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005735 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005736 return false;
5737 }
5738
5739 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005740 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005741 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5742 {
5743 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005744 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005745 return false;
5746 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005747 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5748 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5749 {
5750 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5751 return false;
5752 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005753
5754 // .. the data would be packed to the buffer object such that the memory writes required
5755 // would exceed the data store size.
5756 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5757 const gl::Extents size(width, height, 1);
5758 const auto &pack = context->getGLState().getPackState();
5759
Jamie Madillca2ff382018-07-11 09:01:17 -04005760 GLuint endByte = 0;
5761 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005762 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005763 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005764 return false;
5765 }
5766
Jamie Madillbe849e42017-05-02 15:49:00 -04005767 if (bufSize >= 0)
5768 {
5769 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5770 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005771 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005772 return false;
5773 }
5774 }
5775
5776 if (pixelPackBuffer != nullptr)
5777 {
5778 CheckedNumeric<size_t> checkedEndByte(endByte);
5779 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5780 checkedEndByte += checkedOffset;
5781
5782 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5783 {
5784 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005785 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005786 return false;
5787 }
5788 }
5789
5790 if (pixelPackBuffer == nullptr && length != nullptr)
5791 {
5792 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5793 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005794 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005795 return false;
5796 }
5797
5798 *length = static_cast<GLsizei>(endByte);
5799 }
5800
Geoff Langa953b522018-02-21 16:56:23 -05005801 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005802 angle::CheckedNumeric<int> clippedExtent(length);
5803 if (start < 0)
5804 {
5805 // "subtract" the area that is less than 0
5806 clippedExtent += start;
5807 }
5808
Geoff Langa953b522018-02-21 16:56:23 -05005809 angle::CheckedNumeric<int> readExtent = start;
5810 readExtent += length;
5811 if (!readExtent.IsValid())
5812 {
5813 return false;
5814 }
5815
5816 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005817 {
5818 // Subtract the region to the right of the read buffer
5819 clippedExtent -= (readExtent - bufferSize);
5820 }
5821
5822 if (!clippedExtent.IsValid())
5823 {
Geoff Langa953b522018-02-21 16:56:23 -05005824 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005825 }
5826
Geoff Langa953b522018-02-21 16:56:23 -05005827 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5828 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005829 };
5830
Geoff Langa953b522018-02-21 16:56:23 -05005831 GLsizei writtenColumns = 0;
5832 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5833 {
5834 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5835 return false;
5836 }
5837
5838 GLsizei writtenRows = 0;
5839 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5840 {
5841 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5842 return false;
5843 }
5844
Jamie Madillbe849e42017-05-02 15:49:00 -04005845 if (columns != nullptr)
5846 {
Geoff Langa953b522018-02-21 16:56:23 -05005847 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005848 }
5849
5850 if (rows != nullptr)
5851 {
Geoff Langa953b522018-02-21 16:56:23 -05005852 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005853 }
5854
5855 return true;
5856}
5857
5858template <typename ParamType>
5859bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005860 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005861 GLenum pname,
5862 GLsizei bufSize,
5863 const ParamType *params)
5864{
5865 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5866 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005867 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005868 return false;
5869 }
5870
5871 if (context->getTargetTexture(target) == nullptr)
5872 {
5873 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005874 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005875 return false;
5876 }
5877
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005878 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005879 if (bufSize >= 0 && bufSize < minBufSize)
5880 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005881 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005882 return false;
5883 }
5884
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005885 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5886 {
5887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5888 return false;
5889 }
5890
Jamie Madillbe849e42017-05-02 15:49:00 -04005891 switch (pname)
5892 {
5893 case GL_TEXTURE_WRAP_R:
5894 case GL_TEXTURE_SWIZZLE_R:
5895 case GL_TEXTURE_SWIZZLE_G:
5896 case GL_TEXTURE_SWIZZLE_B:
5897 case GL_TEXTURE_SWIZZLE_A:
5898 case GL_TEXTURE_BASE_LEVEL:
5899 case GL_TEXTURE_MAX_LEVEL:
5900 case GL_TEXTURE_COMPARE_MODE:
5901 case GL_TEXTURE_COMPARE_FUNC:
5902 case GL_TEXTURE_MIN_LOD:
5903 case GL_TEXTURE_MAX_LOD:
5904 if (context->getClientMajorVersion() < 3)
5905 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005906 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005907 return false;
5908 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005909 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005910 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005911 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5912 "available without "
5913 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005914 return false;
5915 }
5916 break;
5917
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005918 case GL_GENERATE_MIPMAP:
5919 case GL_TEXTURE_CROP_RECT_OES:
5920 if (context->getClientMajorVersion() > 1)
5921 {
5922 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5923 return false;
5924 }
5925 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005926 default:
5927 break;
5928 }
5929
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005930 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005931 {
5932 switch (pname)
5933 {
5934 case GL_TEXTURE_MIN_FILTER:
5935 case GL_TEXTURE_MAG_FILTER:
5936 case GL_TEXTURE_WRAP_S:
5937 case GL_TEXTURE_WRAP_T:
5938 case GL_TEXTURE_WRAP_R:
5939 case GL_TEXTURE_MIN_LOD:
5940 case GL_TEXTURE_MAX_LOD:
5941 case GL_TEXTURE_COMPARE_MODE:
5942 case GL_TEXTURE_COMPARE_FUNC:
5943 context->handleError(InvalidEnum()
5944 << "Invalid parameter for 2D multisampled textures.");
5945 return false;
5946 }
5947 }
5948
Jamie Madillbe849e42017-05-02 15:49:00 -04005949 switch (pname)
5950 {
5951 case GL_TEXTURE_WRAP_S:
5952 case GL_TEXTURE_WRAP_T:
5953 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005954 {
5955 bool restrictedWrapModes =
5956 target == TextureType::External || target == TextureType::Rectangle;
5957 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005958 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005959 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005960 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005961 }
5962 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005963
5964 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005965 {
5966 bool restrictedMinFilter =
5967 target == TextureType::External || target == TextureType::Rectangle;
5968 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005969 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005970 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005971 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005972 }
5973 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005974
5975 case GL_TEXTURE_MAG_FILTER:
5976 if (!ValidateTextureMagFilterValue(context, params))
5977 {
5978 return false;
5979 }
5980 break;
5981
5982 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005983 if (!context->getExtensions().textureUsage)
5984 {
5985 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5986 return false;
5987 }
5988
Jamie Madillbe849e42017-05-02 15:49:00 -04005989 switch (ConvertToGLenum(params[0]))
5990 {
5991 case GL_NONE:
5992 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5993 break;
5994
5995 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005996 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005997 return false;
5998 }
5999 break;
6000
6001 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07006002 {
6003 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6004 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04006005 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006006 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006007 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006008 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6009 }
6010 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006011
6012 case GL_TEXTURE_MIN_LOD:
6013 case GL_TEXTURE_MAX_LOD:
6014 // any value is permissible
6015 break;
6016
6017 case GL_TEXTURE_COMPARE_MODE:
6018 if (!ValidateTextureCompareModeValue(context, params))
6019 {
6020 return false;
6021 }
6022 break;
6023
6024 case GL_TEXTURE_COMPARE_FUNC:
6025 if (!ValidateTextureCompareFuncValue(context, params))
6026 {
6027 return false;
6028 }
6029 break;
6030
6031 case GL_TEXTURE_SWIZZLE_R:
6032 case GL_TEXTURE_SWIZZLE_G:
6033 case GL_TEXTURE_SWIZZLE_B:
6034 case GL_TEXTURE_SWIZZLE_A:
6035 switch (ConvertToGLenum(params[0]))
6036 {
6037 case GL_RED:
6038 case GL_GREEN:
6039 case GL_BLUE:
6040 case GL_ALPHA:
6041 case GL_ZERO:
6042 case GL_ONE:
6043 break;
6044
6045 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006046 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006047 return false;
6048 }
6049 break;
6050
6051 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006052 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006054 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006055 return false;
6056 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006057 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006058 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006059 context->handleError(InvalidOperation()
6060 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006061 return false;
6062 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006063 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006064 {
6065 context->handleError(InvalidOperation()
6066 << "Base level must be 0 for multisampled textures.");
6067 return false;
6068 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006069 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006070 {
6071 context->handleError(InvalidOperation()
6072 << "Base level must be 0 for rectangle textures.");
6073 return false;
6074 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006075 break;
6076
6077 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006078 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006080 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006081 return false;
6082 }
6083 break;
6084
6085 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6086 if (context->getClientVersion() < Version(3, 1))
6087 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006088 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006089 return false;
6090 }
6091 switch (ConvertToGLenum(params[0]))
6092 {
6093 case GL_DEPTH_COMPONENT:
6094 case GL_STENCIL_INDEX:
6095 break;
6096
6097 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006098 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006099 return false;
6100 }
6101 break;
6102
6103 case GL_TEXTURE_SRGB_DECODE_EXT:
6104 if (!ValidateTextureSRGBDecodeValue(context, params))
6105 {
6106 return false;
6107 }
6108 break;
6109
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006110 case GL_GENERATE_MIPMAP:
6111 case GL_TEXTURE_CROP_RECT_OES:
6112 if (context->getClientMajorVersion() > 1)
6113 {
6114 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6115 return false;
6116 }
6117 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006118 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006120 return false;
6121 }
6122
6123 return true;
6124}
6125
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006126template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6127template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006128
Jamie Madill5b772312018-03-08 20:28:32 -05006129bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006130{
6131 if (index >= MAX_VERTEX_ATTRIBS)
6132 {
6133 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6134 return false;
6135 }
6136
6137 return true;
6138}
6139
6140bool ValidateGetActiveUniformBlockivBase(Context *context,
6141 GLuint program,
6142 GLuint uniformBlockIndex,
6143 GLenum pname,
6144 GLsizei *length)
6145{
6146 if (length)
6147 {
6148 *length = 0;
6149 }
6150
6151 if (context->getClientMajorVersion() < 3)
6152 {
6153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6154 return false;
6155 }
6156
6157 Program *programObject = GetValidProgram(context, program);
6158 if (!programObject)
6159 {
6160 return false;
6161 }
6162
6163 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6164 {
6165 context->handleError(InvalidValue()
6166 << "uniformBlockIndex exceeds active uniform block count.");
6167 return false;
6168 }
6169
6170 switch (pname)
6171 {
6172 case GL_UNIFORM_BLOCK_BINDING:
6173 case GL_UNIFORM_BLOCK_DATA_SIZE:
6174 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6175 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6176 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6177 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6178 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6179 break;
6180
6181 default:
6182 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6183 return false;
6184 }
6185
6186 if (length)
6187 {
6188 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6189 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006190 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006191 programObject->getUniformBlockByIndex(uniformBlockIndex);
6192 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6193 }
6194 else
6195 {
6196 *length = 1;
6197 }
6198 }
6199
6200 return true;
6201}
6202
Jamie Madill9696d072017-08-26 23:19:57 -04006203template <typename ParamType>
6204bool ValidateSamplerParameterBase(Context *context,
6205 GLuint sampler,
6206 GLenum pname,
6207 GLsizei bufSize,
6208 ParamType *params)
6209{
6210 if (context->getClientMajorVersion() < 3)
6211 {
6212 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6213 return false;
6214 }
6215
6216 if (!context->isSampler(sampler))
6217 {
6218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6219 return false;
6220 }
6221
6222 const GLsizei minBufSize = 1;
6223 if (bufSize >= 0 && bufSize < minBufSize)
6224 {
6225 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6226 return false;
6227 }
6228
6229 switch (pname)
6230 {
6231 case GL_TEXTURE_WRAP_S:
6232 case GL_TEXTURE_WRAP_T:
6233 case GL_TEXTURE_WRAP_R:
6234 if (!ValidateTextureWrapModeValue(context, params, false))
6235 {
6236 return false;
6237 }
6238 break;
6239
6240 case GL_TEXTURE_MIN_FILTER:
6241 if (!ValidateTextureMinFilterValue(context, params, false))
6242 {
6243 return false;
6244 }
6245 break;
6246
6247 case GL_TEXTURE_MAG_FILTER:
6248 if (!ValidateTextureMagFilterValue(context, params))
6249 {
6250 return false;
6251 }
6252 break;
6253
6254 case GL_TEXTURE_MIN_LOD:
6255 case GL_TEXTURE_MAX_LOD:
6256 // any value is permissible
6257 break;
6258
6259 case GL_TEXTURE_COMPARE_MODE:
6260 if (!ValidateTextureCompareModeValue(context, params))
6261 {
6262 return false;
6263 }
6264 break;
6265
6266 case GL_TEXTURE_COMPARE_FUNC:
6267 if (!ValidateTextureCompareFuncValue(context, params))
6268 {
6269 return false;
6270 }
6271 break;
6272
6273 case GL_TEXTURE_SRGB_DECODE_EXT:
6274 if (!ValidateTextureSRGBDecodeValue(context, params))
6275 {
6276 return false;
6277 }
6278 break;
6279
Luc Ferron1b1a8642018-01-23 15:12:01 -05006280 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6281 {
6282 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6283 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6284 {
6285 return false;
6286 }
6287 }
6288 break;
6289
Jamie Madill9696d072017-08-26 23:19:57 -04006290 default:
6291 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6292 return false;
6293 }
6294
6295 return true;
6296}
6297
6298template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6299template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6300
6301bool ValidateGetSamplerParameterBase(Context *context,
6302 GLuint sampler,
6303 GLenum pname,
6304 GLsizei *length)
6305{
6306 if (length)
6307 {
6308 *length = 0;
6309 }
6310
6311 if (context->getClientMajorVersion() < 3)
6312 {
6313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6314 return false;
6315 }
6316
6317 if (!context->isSampler(sampler))
6318 {
6319 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6320 return false;
6321 }
6322
6323 switch (pname)
6324 {
6325 case GL_TEXTURE_WRAP_S:
6326 case GL_TEXTURE_WRAP_T:
6327 case GL_TEXTURE_WRAP_R:
6328 case GL_TEXTURE_MIN_FILTER:
6329 case GL_TEXTURE_MAG_FILTER:
6330 case GL_TEXTURE_MIN_LOD:
6331 case GL_TEXTURE_MAX_LOD:
6332 case GL_TEXTURE_COMPARE_MODE:
6333 case GL_TEXTURE_COMPARE_FUNC:
6334 break;
6335
Luc Ferron1b1a8642018-01-23 15:12:01 -05006336 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6337 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6338 {
6339 return false;
6340 }
6341 break;
6342
Jamie Madill9696d072017-08-26 23:19:57 -04006343 case GL_TEXTURE_SRGB_DECODE_EXT:
6344 if (!context->getExtensions().textureSRGBDecode)
6345 {
6346 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6347 return false;
6348 }
6349 break;
6350
6351 default:
6352 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6353 return false;
6354 }
6355
6356 if (length)
6357 {
6358 *length = 1;
6359 }
6360 return true;
6361}
6362
6363bool ValidateGetInternalFormativBase(Context *context,
6364 GLenum target,
6365 GLenum internalformat,
6366 GLenum pname,
6367 GLsizei bufSize,
6368 GLsizei *numParams)
6369{
6370 if (numParams)
6371 {
6372 *numParams = 0;
6373 }
6374
6375 if (context->getClientMajorVersion() < 3)
6376 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006377 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006378 return false;
6379 }
6380
6381 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006382 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006383 {
6384 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6385 return false;
6386 }
6387
6388 switch (target)
6389 {
6390 case GL_RENDERBUFFER:
6391 break;
6392
6393 case GL_TEXTURE_2D_MULTISAMPLE:
6394 if (context->getClientVersion() < ES_3_1)
6395 {
6396 context->handleError(InvalidOperation()
6397 << "Texture target requires at least OpenGL ES 3.1.");
6398 return false;
6399 }
6400 break;
6401
6402 default:
6403 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6404 return false;
6405 }
6406
6407 if (bufSize < 0)
6408 {
6409 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6410 return false;
6411 }
6412
6413 GLsizei maxWriteParams = 0;
6414 switch (pname)
6415 {
6416 case GL_NUM_SAMPLE_COUNTS:
6417 maxWriteParams = 1;
6418 break;
6419
6420 case GL_SAMPLES:
6421 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6422 break;
6423
6424 default:
6425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6426 return false;
6427 }
6428
6429 if (numParams)
6430 {
6431 // glGetInternalFormativ will not overflow bufSize
6432 *numParams = std::min(bufSize, maxWriteParams);
6433 }
6434
6435 return true;
6436}
6437
Jamie Madille98b1b52018-03-08 09:47:23 -05006438bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6439{
Jamie Madill427064d2018-04-13 16:20:34 -04006440 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006441 {
6442 context->handleError(InvalidOperation());
6443 return false;
6444 }
6445 return true;
6446}
6447
Lingfeng Yang038dd532018-03-29 17:31:52 -07006448bool ValidateMultitextureUnit(Context *context, GLenum texture)
6449{
6450 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6451 {
6452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6453 return false;
6454 }
6455 return true;
6456}
6457
Jamie Madillc29968b2016-01-20 11:17:23 -05006458} // namespace gl