blob: 9f25a53f36250c257593af68770dacc73109805b [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"
Jamie Madill231c7f52017-04-26 13:45:37 -040025#include "libANGLE/validationES2.h"
26#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28#include "common/mathutil.h"
29#include "common/utilities.h"
30
Jamie Madille2e406c2016-06-02 13:04:10 -040031using namespace angle;
32
Geoff Lange8ebe7f2013-08-05 15:03:13 -040033namespace gl
34{
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050037bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
38{
39 // List of compressed format that require that the texture size is smaller than or a multiple of
40 // the compressed block size.
41 switch (internalFormat)
42 {
43 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
44 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
46 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
47 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
51 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
52 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
53 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
57 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 return true;
jchen10a99ed552017-09-22 08:10:32 +080059
Luc Ferron9dbaeba2018-02-01 07:26:59 -050060 default:
61 return false;
62 }
63}
64bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
65{
66 // Compressed sub textures have additional formats that requires exact size.
67 // ES 3.1, Section 8.7, Page 171
68 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
69 IsETC2EACFormat(internalFormat);
70}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030071
72bool DifferenceCanOverflow(GLint a, GLint b)
73{
74 CheckedNumeric<GLint> checkedA(a);
75 checkedA -= b;
76 // Use negation to make sure that the difference can't overflow regardless of the order.
77 checkedA = -checkedA;
78 return !checkedA.IsValid();
79}
80
Jamie Madill5b772312018-03-08 20:28:32 -050081bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040082{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070083 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040084 const gl::Program *program = state.getProgram();
85
Corentin Wallez327411e2016-12-09 11:09:17 -050086 bool webglCompatibility = context->getExtensions().webglCompatibility;
87
Jamie Madill51af38b2018-04-15 08:50:56 -040088 const VertexArray *vao = state.getVertexArray();
89 const AttributesMask &clientAttribs = vao->getEnabledClientMemoryAttribsMask();
90
91 if (clientAttribs.any())
92 {
93 if (webglCompatibility || !state.areClientArraysEnabled())
94 {
95 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
96 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
97 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
98 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
99 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
100 return false;
101 }
102 else if (vao->hasEnabledNullPointerClientArray())
103 {
104 // This is an application error that would normally result in a crash, but we catch it
105 // and return an error
106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
107 return false;
108 }
109 }
110
111 // If we're drawing zero vertices, we have enough data.
112 if (vertexCount <= 0 || primcount <= 0)
113 {
114 return true;
115 }
116
Jamie Madill231c7f52017-04-26 13:45:37 -0400117 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800118 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill51af38b2018-04-15 08:50:56 -0400119
Lingfeng Yang461b09a2018-04-23 09:02:09 -0700120 bool isGLES1 = context->getClientVersion() < Version(2, 0);
121
122 const AttributesMask &activeAttribs = ((isGLES1 ? context->getVertexArraysAttributeMask()
123 : program->getActiveAttribLocationsMask()) &
Jamie Madill02c9c042018-04-17 13:43:48 -0400124 vao->getEnabledAttributesMask() & ~clientAttribs);
Jamie Madill51af38b2018-04-15 08:50:56 -0400125
126 for (size_t attributeIndex : activeAttribs)
Jamie Madill1ca74672015-07-21 15:14:11 -0400127 {
128 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400129 ASSERT(attrib.enabled);
Corentin Wallez672f7f32017-06-15 17:42:17 -0400130
Lingfeng Yang038dd532018-03-29 17:31:52 -0700131 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Lingfeng Yang461b09a2018-04-23 09:02:09 -0700132 ASSERT(isGLES1 || program->isAttribLocationActive(attributeIndex));
Corentin Wallezfd456442016-12-21 17:57:00 -0500133
Jamie Madill02c9c042018-04-17 13:43:48 -0400134 GLint maxVertexElement = maxVertex;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300135 GLuint divisor = binding.getDivisor();
Jamie Madill02c9c042018-04-17 13:43:48 -0400136 if (divisor != 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500137 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300138 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500139 }
140
141 // We do manual overflow checks here instead of using safe_math.h because it was
142 // a bottleneck. Thanks to some properties of GL we know inequalities that can
143 // help us make the overflow checks faster.
144
145 // The max possible attribSize is 16 for a vector of 4 32 bit values.
146 constexpr uint64_t kMaxAttribSize = 16;
147 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
148 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
149
150 // We know attribStride is given as a GLsizei which is typedefed to int.
151 // We also know an upper bound for attribSize.
Jamie Madill02c9c042018-04-17 13:43:48 -0400152 static_assert(std::is_same<int, GLsizei>::value, "Unexpected type");
153 ASSERT(ComputeVertexAttributeStride(attrib, binding) == binding.getStride());
154 uint64_t attribStride = binding.getStride();
155 ASSERT(attribStride <= kIntMax && ComputeVertexAttributeTypeSize(attrib) <= kMaxAttribSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500156
Jamie Madill02c9c042018-04-17 13:43:48 -0400157 // Computing the product of two 32-bit ints will fit in 64 bits without overflow.
158 static_assert(kIntMax * kIntMax < kUint64Max, "Unexpected overflow");
159 uint64_t attribDataSizeMinusAttribSize = maxVertexElement * attribStride;
Corentin Wallezfd456442016-12-21 17:57:00 -0500160
161 // An overflow can happen when adding the offset, check for it.
Jamie Madill02c9c042018-04-17 13:43:48 -0400162 if (attribDataSizeMinusAttribSize > kUint64Max - attrib.cachedSizePlusRelativeOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500163 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700164 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500165 return false;
166 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500167
168 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
Jamie Madill02c9c042018-04-17 13:43:48 -0400169 // We can return INVALID_OPERATION if our array buffer does not have enough backing data.
170 if (attribDataSizeMinusAttribSize + attrib.cachedSizePlusRelativeOffset >
171 binding.getCachedBufferSizeMinusOffset())
Corentin Wallezfd456442016-12-21 17:57:00 -0500172 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500174 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400175 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400176 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800177
Jamie Madill7267aa62018-04-17 15:28:21 -0400178 if (webglCompatibility && vao->hasTransformFeedbackBindingConflict(activeAttribs))
Jamie Madill02c9c042018-04-17 13:43:48 -0400179 {
Jamie Madill7267aa62018-04-17 15:28:21 -0400180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexBufferBoundForTransformFeedback);
181 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400182 }
183
184 return true;
185}
186
Jamie Madill5b772312018-03-08 20:28:32 -0500187bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400188{
189 switch (type)
190 {
191 // Types referenced in Table 3.4 of the ES 2.0.25 spec
192 case GL_UNSIGNED_BYTE:
193 case GL_UNSIGNED_SHORT_4_4_4_4:
194 case GL_UNSIGNED_SHORT_5_5_5_1:
195 case GL_UNSIGNED_SHORT_5_6_5:
196 return context->getClientVersion() >= ES_2_0;
197
198 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
199 case GL_BYTE:
200 case GL_INT:
201 case GL_SHORT:
202 case GL_UNSIGNED_INT:
203 case GL_UNSIGNED_INT_10F_11F_11F_REV:
204 case GL_UNSIGNED_INT_24_8:
205 case GL_UNSIGNED_INT_2_10_10_10_REV:
206 case GL_UNSIGNED_INT_5_9_9_9_REV:
207 case GL_UNSIGNED_SHORT:
208 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
209 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
210 return context->getClientVersion() >= ES_3_0;
211
212 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400213 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
214 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400215
216 case GL_HALF_FLOAT:
217 return context->getClientVersion() >= ES_3_0 ||
218 context->getExtensions().textureHalfFloat;
219
220 case GL_HALF_FLOAT_OES:
221 return context->getExtensions().colorBufferHalfFloat;
222
223 default:
224 return false;
225 }
226}
227
Jamie Madill5b772312018-03-08 20:28:32 -0500228bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400229{
230 switch (format)
231 {
232 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
233 case GL_RGBA:
234 case GL_RGB:
235 case GL_ALPHA:
236 return context->getClientVersion() >= ES_2_0;
237
238 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
239 case GL_RG:
240 case GL_RED:
241 case GL_RGBA_INTEGER:
242 case GL_RGB_INTEGER:
243 case GL_RG_INTEGER:
244 case GL_RED_INTEGER:
245 return context->getClientVersion() >= ES_3_0;
246
247 case GL_SRGB_ALPHA_EXT:
248 case GL_SRGB_EXT:
249 return context->getExtensions().sRGB;
250
251 case GL_BGRA_EXT:
252 return context->getExtensions().readFormatBGRA;
253
254 default:
255 return false;
256 }
257}
258
Jamie Madill5b772312018-03-08 20:28:32 -0500259bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400260 GLenum framebufferComponentType,
261 GLenum format,
262 GLenum type)
263{
264 switch (framebufferComponentType)
265 {
266 case GL_UNSIGNED_NORMALIZED:
267 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
268 // ReadPixels with BGRA even if the extension is not present
269 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
270 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
271 type == GL_UNSIGNED_BYTE);
272
273 case GL_SIGNED_NORMALIZED:
274 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
275
276 case GL_INT:
277 return (format == GL_RGBA_INTEGER && type == GL_INT);
278
279 case GL_UNSIGNED_INT:
280 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
281
282 case GL_FLOAT:
283 return (format == GL_RGBA && type == GL_FLOAT);
284
285 default:
286 UNREACHABLE();
287 return false;
288 }
289}
290
Geoff Langc1984ed2016-10-07 12:41:00 -0400291template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400292bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400293{
294 switch (ConvertToGLenum(params[0]))
295 {
296 case GL_CLAMP_TO_EDGE:
297 break;
298
299 case GL_REPEAT:
300 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400301 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400302 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400303 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700304 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 return false;
306 }
307 break;
308
309 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700310 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400311 return false;
312 }
313
314 return true;
315}
316
317template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400318bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400319{
320 switch (ConvertToGLenum(params[0]))
321 {
322 case GL_NEAREST:
323 case GL_LINEAR:
324 break;
325
326 case GL_NEAREST_MIPMAP_NEAREST:
327 case GL_LINEAR_MIPMAP_NEAREST:
328 case GL_NEAREST_MIPMAP_LINEAR:
329 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400330 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400331 {
332 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700333 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400334 return false;
335 }
336 break;
337
338 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400340 return false;
341 }
342
343 return true;
344}
345
346template <typename ParamType>
347bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
348{
349 switch (ConvertToGLenum(params[0]))
350 {
351 case GL_NEAREST:
352 case GL_LINEAR:
353 break;
354
355 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700356 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400357 return false;
358 }
359
360 return true;
361}
362
363template <typename ParamType>
364bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
365{
366 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
367 switch (ConvertToGLenum(params[0]))
368 {
369 case GL_NONE:
370 case GL_COMPARE_REF_TO_TEXTURE:
371 break;
372
373 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400375 return false;
376 }
377
378 return true;
379}
380
381template <typename ParamType>
382bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
383{
384 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
385 switch (ConvertToGLenum(params[0]))
386 {
387 case GL_LEQUAL:
388 case GL_GEQUAL:
389 case GL_LESS:
390 case GL_GREATER:
391 case GL_EQUAL:
392 case GL_NOTEQUAL:
393 case GL_ALWAYS:
394 case GL_NEVER:
395 break;
396
397 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400399 return false;
400 }
401
402 return true;
403}
404
405template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700406bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
407{
408 if (!context->getExtensions().textureSRGBDecode)
409 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700410 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700411 return false;
412 }
413
414 switch (ConvertToGLenum(params[0]))
415 {
416 case GL_DECODE_EXT:
417 case GL_SKIP_DECODE_EXT:
418 break;
419
420 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700422 return false;
423 }
424
425 return true;
426}
427
Luc Ferron1b1a8642018-01-23 15:12:01 -0500428bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
429{
430 if (!context->getExtensions().textureFilterAnisotropic)
431 {
432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
433 return false;
434 }
435
436 return true;
437}
438
439bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
440{
441 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
442 {
443 return false;
444 }
445
446 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
447
448 if (paramValue < 1 || paramValue > largest)
449 {
450 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
451 return false;
452 }
453
454 return true;
455}
456
Jamie Madill5b772312018-03-08 20:28:32 -0500457bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400458{
459 const Program *program = context->getGLState().getProgram();
460 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
461
Brandon Jonesc405ae72017-12-06 14:15:03 -0800462 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
463 framebuffer->getDrawBufferTypeMask().to_ulong(),
464 program->getActiveOutputVariables().to_ulong(),
465 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400466 {
Brandon Jones76746f92017-11-22 11:44:41 -0800467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
468 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400469 }
470
471 return true;
472}
473
Jamie Madill5b772312018-03-08 20:28:32 -0500474bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400475{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700476 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400477 const Program *program = context->getGLState().getProgram();
478 const VertexArray *vao = context->getGLState().getVertexArray();
479
Brandon Jonesc405ae72017-12-06 14:15:03 -0800480 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
481 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
482 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
483
484 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
485 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
486 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
487
488 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
489 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400490 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800491 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
492 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400493 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400494 return true;
495}
496
Jiawei Shaofccebff2018-03-08 13:51:02 +0800497bool IsCompatibleDrawModeWithGeometryShader(GLenum drawMode,
498 GLenum geometryShaderInputPrimitiveType)
499{
500 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
501 switch (geometryShaderInputPrimitiveType)
502 {
503 case GL_POINTS:
504 return drawMode == GL_POINTS;
505 case GL_LINES:
506 return drawMode == GL_LINES || drawMode == GL_LINE_STRIP || drawMode == GL_LINE_LOOP;
507 case GL_LINES_ADJACENCY_EXT:
508 return drawMode == GL_LINES_ADJACENCY_EXT || drawMode == GL_LINE_STRIP_ADJACENCY_EXT;
509 case GL_TRIANGLES:
510 return drawMode == GL_TRIANGLES || drawMode == GL_TRIANGLE_FAN ||
511 drawMode == GL_TRIANGLE_STRIP;
512 case GL_TRIANGLES_ADJACENCY_EXT:
513 return drawMode == GL_TRIANGLES_ADJACENCY_EXT ||
514 drawMode == GL_TRIANGLE_STRIP_ADJACENCY_EXT;
515 default:
516 UNREACHABLE();
517 return false;
518 }
519}
520
Geoff Langf41a7152016-09-19 15:11:17 -0400521} // anonymous namespace
522
Brandon Jonesd1049182018-03-28 10:02:20 -0700523void SetRobustLengthParam(GLsizei *length, GLsizei value)
524{
525 if (length)
526 {
527 *length = value;
528 }
529}
530
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500531bool IsETC2EACFormat(const GLenum format)
532{
533 // ES 3.1, Table 8.19
534 switch (format)
535 {
536 case GL_COMPRESSED_R11_EAC:
537 case GL_COMPRESSED_SIGNED_R11_EAC:
538 case GL_COMPRESSED_RG11_EAC:
539 case GL_COMPRESSED_SIGNED_RG11_EAC:
540 case GL_COMPRESSED_RGB8_ETC2:
541 case GL_COMPRESSED_SRGB8_ETC2:
542 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
543 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
544 case GL_COMPRESSED_RGBA8_ETC2_EAC:
545 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
546 return true;
547
548 default:
549 return false;
550 }
551}
552
Jamie Madill5b772312018-03-08 20:28:32 -0500553bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400554{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800555 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400556 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800557 case TextureType::_2D:
558 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800559 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400560
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800561 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400562 return context->getExtensions().textureRectangle;
563
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800564 case TextureType::_3D:
565 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800566 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500567
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800568 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800569 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400570
He Yunchaoced53ae2016-11-29 15:00:51 +0800571 default:
572 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500573 }
Jamie Madill35d15012013-10-07 10:46:37 -0400574}
575
Jamie Madill5b772312018-03-08 20:28:32 -0500576bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500577{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800578 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500579 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800580 case TextureType::_2D:
581 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500582 return true;
583
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800584 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400585 return context->getExtensions().textureRectangle;
586
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500587 default:
588 return false;
589 }
590}
591
Jamie Madill5b772312018-03-08 20:28:32 -0500592bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500593{
594 switch (target)
595 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800596 case TextureType::_3D:
597 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300598 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500599
600 default:
601 return false;
602 }
603}
604
Ian Ewellbda75592016-04-18 17:25:54 -0400605// Most texture GL calls are not compatible with external textures, so we have a separate validation
606// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500607bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400608{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800609 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400610 (context->getExtensions().eglImageExternal ||
611 context->getExtensions().eglStreamConsumerExternal);
612}
613
Shannon Woods4dfed832014-03-17 20:03:39 -0400614// This function differs from ValidTextureTarget in that the target must be
615// usable as the destination of a 2D operation-- so a cube face is valid, but
616// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400617// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500618bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400619{
620 switch (target)
621 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800622 case TextureTarget::_2D:
623 case TextureTarget::CubeMapNegativeX:
624 case TextureTarget::CubeMapNegativeY:
625 case TextureTarget::CubeMapNegativeZ:
626 case TextureTarget::CubeMapPositiveX:
627 case TextureTarget::CubeMapPositiveY:
628 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800629 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800630 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400631 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800632 default:
633 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500634 }
635}
636
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800637bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
638 GLenum transformFeedbackPrimitiveMode,
639 GLenum renderPrimitiveMode)
640{
641 ASSERT(context);
642
643 if (!context->getExtensions().geometryShader)
644 {
645 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
646 // that does not match the current transform feedback object's draw mode (if transform
647 // feedback is active), (3.0.2, section 2.14, pg 86)
648 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
649 }
650
651 // [GL_EXT_geometry_shader] Table 12.1gs
652 switch (transformFeedbackPrimitiveMode)
653 {
654 case GL_POINTS:
655 return renderPrimitiveMode == GL_POINTS;
656 case GL_TRIANGLES:
657 return renderPrimitiveMode == GL_TRIANGLES ||
658 renderPrimitiveMode == GL_TRIANGLE_STRIP ||
659 renderPrimitiveMode == GL_TRIANGLE_FAN;
660 case GL_LINES:
661 return renderPrimitiveMode == GL_LINES || renderPrimitiveMode == GL_LINE_LOOP ||
662 renderPrimitiveMode == GL_LINE_STRIP;
663 default:
664 UNREACHABLE();
665 return false;
666 }
667}
668
Jamie Madill5b772312018-03-08 20:28:32 -0500669bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -0400670 GLenum mode,
671 GLsizei count,
672 GLenum type,
673 const GLvoid *indices,
674 GLsizei primcount)
675{
676 if (primcount < 0)
677 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700678 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400679 return false;
680 }
681
682 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
683 {
684 return false;
685 }
686
Jamie Madill9fdaa492018-02-16 10:52:11 -0500687 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400688}
689
690bool ValidateDrawArraysInstancedBase(Context *context,
691 GLenum mode,
692 GLint first,
693 GLsizei count,
694 GLsizei primcount)
695{
696 if (primcount < 0)
697 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700698 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400699 return false;
700 }
701
702 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
703 {
704 return false;
705 }
706
Jamie Madill9fdaa492018-02-16 10:52:11 -0500707 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400708}
709
Jamie Madill5b772312018-03-08 20:28:32 -0500710bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400711{
712 // Verify there is at least one active attribute with a divisor of zero
713 const State &state = context->getGLState();
714
715 Program *program = state.getProgram();
716
717 const auto &attribs = state.getVertexArray()->getVertexAttributes();
718 const auto &bindings = state.getVertexArray()->getVertexBindings();
719 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
720 {
721 const VertexAttribute &attrib = attribs[attributeIndex];
722 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300723 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400724 {
725 return true;
726 }
727 }
728
Brandon Jonesafa75152017-07-21 13:11:29 -0700729 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400730 return false;
731}
732
Jamie Madill5b772312018-03-08 20:28:32 -0500733bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500734{
735 switch (target)
736 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800737 case TextureType::_3D:
738 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800739 return true;
740 default:
741 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400742 }
743}
744
Jamie Madill5b772312018-03-08 20:28:32 -0500745bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800746{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800747 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800748 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800749 case TextureType::_2D:
750 case TextureType::_2DArray:
751 case TextureType::_2DMultisample:
752 case TextureType::CubeMap:
753 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800754 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800755 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400756 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800757 default:
758 return false;
759 }
760}
761
Jamie Madill5b772312018-03-08 20:28:32 -0500762bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500763{
He Yunchaoced53ae2016-11-29 15:00:51 +0800764 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
765 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400766 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500767
768 switch (target)
769 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800770 case GL_FRAMEBUFFER:
771 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400772
He Yunchaoced53ae2016-11-29 15:00:51 +0800773 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800774 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400775 return (context->getExtensions().framebufferBlit ||
776 context->getClientMajorVersion() >= 3);
777
He Yunchaoced53ae2016-11-29 15:00:51 +0800778 default:
779 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500780 }
781}
782
Jamie Madill5b772312018-03-08 20:28:32 -0500783bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400784{
Jamie Madillc29968b2016-01-20 11:17:23 -0500785 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400786 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800787 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400788 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800789 case TextureType::_2D:
790 case TextureType::_2DArray:
791 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500792 maxDimension = caps.max2DTextureSize;
793 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800794 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800795 maxDimension = caps.maxCubeMapTextureSize;
796 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800797 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400798 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800799 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800800 maxDimension = caps.max3DTextureSize;
801 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800802 default:
803 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400804 }
805
Brandon Jones6cad5662017-06-14 13:25:13 -0700806 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400807}
808
Jamie Madill5b772312018-03-08 20:28:32 -0500809bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800810 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700811 GLint level,
812 GLsizei width,
813 GLsizei height,
814 GLsizei depth,
815 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400816{
Brandon Jones6cad5662017-06-14 13:25:13 -0700817 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400818 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700819 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400820 return false;
821 }
Austin Kinross08528e12015-10-07 16:24:40 -0700822 // TexSubImage parameters can be NPOT without textureNPOT extension,
823 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500824 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500825 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500826 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400827 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400828 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700829 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400830 return false;
831 }
832
833 if (!ValidMipLevel(context, target, level))
834 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700835 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400836 return false;
837 }
838
839 return true;
840}
841
Geoff Lang966c9402017-04-18 12:38:27 -0400842bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
843{
844 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
845 (size % blockSize == 0);
846}
847
Jamie Madill5b772312018-03-08 20:28:32 -0500848bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500849 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400850 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500851 GLsizei width,
852 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400853{
Geoff Langca271392017-04-05 12:30:00 -0400854 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400855 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400856 {
857 return false;
858 }
859
Geoff Lang966c9402017-04-18 12:38:27 -0400860 if (width < 0 || height < 0)
861 {
862 return false;
863 }
864
865 if (CompressedTextureFormatRequiresExactSize(internalFormat))
866 {
867 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
868 // block size for level 0 but WebGL disallows this.
869 bool smallerThanBlockSizeAllowed =
870 level > 0 || !context->getExtensions().webglCompatibility;
871
872 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
873 smallerThanBlockSizeAllowed) ||
874 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
875 smallerThanBlockSizeAllowed))
876 {
877 return false;
878 }
879 }
880
881 return true;
882}
883
Jamie Madill5b772312018-03-08 20:28:32 -0500884bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400885 GLenum internalFormat,
886 GLint xoffset,
887 GLint yoffset,
888 GLsizei width,
889 GLsizei height,
890 size_t textureWidth,
891 size_t textureHeight)
892{
893 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
894 if (!formatInfo.compressed)
895 {
896 return false;
897 }
898
Geoff Lang44ff5a72017-02-03 15:15:43 -0500899 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400900 {
901 return false;
902 }
903
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500904 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400905 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500906 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400907 yoffset % formatInfo.compressedBlockHeight != 0)
908 {
909 return false;
910 }
911
912 // Allowed to either have data that is a multiple of block size or is smaller than the block
913 // size but fills the entire mip
914 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
915 static_cast<size_t>(width) == textureWidth &&
916 static_cast<size_t>(height) == textureHeight;
917 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
918 (height % formatInfo.compressedBlockHeight) == 0;
919 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400920 {
921 return false;
922 }
923 }
924
Geoff Langd4f180b2013-09-24 13:57:44 -0400925 return true;
926}
927
Jamie Madill5b772312018-03-08 20:28:32 -0500928bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800929 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400930 GLsizei width,
931 GLsizei height,
932 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400933 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400934 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400935 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400936 GLsizei imageSize)
937{
Corentin Wallez336129f2017-10-17 15:55:40 -0400938 gl::Buffer *pixelUnpackBuffer =
939 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400940 if (pixelUnpackBuffer == nullptr && imageSize < 0)
941 {
942 // Checks are not required
943 return true;
944 }
945
946 // ...the data would be unpacked from the buffer object such that the memory reads required
947 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400948 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
949 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400950 const gl::Extents size(width, height, depth);
951 const auto &unpack = context->getGLState().getUnpackState();
952
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800953 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400954 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
955 if (endByteOrErr.isError())
956 {
957 context->handleError(endByteOrErr.getError());
958 return false;
959 }
960
961 GLuint endByte = endByteOrErr.getResult();
962
963 if (pixelUnpackBuffer)
964 {
965 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
966 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
967 checkedEndByte += checkedOffset;
968
969 if (!checkedEndByte.IsValid() ||
970 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
971 {
972 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500973 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400974 return false;
975 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800976 if (context->getExtensions().webglCompatibility &&
977 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
978 {
979 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
980 PixelUnpackBufferBoundForTransformFeedback);
981 return false;
982 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400983 }
984 else
985 {
986 ASSERT(imageSize >= 0);
987 if (pixels == nullptr && imageSize != 0)
988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500989 context->handleError(InvalidOperation()
990 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400991 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400992 }
993
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400994 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500996 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400997 return false;
998 }
999 }
1000
1001 return true;
1002}
1003
Corentin Wallezad3ae902018-03-09 13:40:42 -05001004bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -05001005{
Geoff Lang37dde692014-01-31 16:34:54 -05001006 switch (queryType)
1007 {
Corentin Wallezad3ae902018-03-09 13:40:42 -05001008 case QueryType::AnySamples:
1009 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001010 return context->getClientMajorVersion() >= 3 ||
1011 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001012 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +08001013 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -05001014 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +08001015 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001016 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +08001017 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001018 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +08001019 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +08001020 default:
1021 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001022 }
1023}
1024
Jamie Madill5b772312018-03-08 20:28:32 -05001025bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001026 GLenum type,
1027 GLboolean normalized,
1028 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001029 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001030 bool pureInteger)
1031{
1032 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001033 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1034 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1035 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1036 // parameter exceeds 255.
1037 constexpr GLsizei kMaxWebGLStride = 255;
1038 if (stride > kMaxWebGLStride)
1039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001040 context->handleError(InvalidValue()
1041 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001042 return false;
1043 }
1044
1045 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1046 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1047 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1048 // or an INVALID_OPERATION error is generated.
1049 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1050 size_t typeSize = GetVertexFormatTypeSize(internalType);
1051
1052 ASSERT(isPow2(typeSize) && typeSize > 0);
1053 size_t sizeMask = (typeSize - 1);
1054 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1055 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001056 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001057 return false;
1058 }
1059
1060 if ((stride & sizeMask) != 0)
1061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001063 return false;
1064 }
1065
1066 return true;
1067}
1068
Jamie Madill5b772312018-03-08 20:28:32 -05001069Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001070{
He Yunchaoced53ae2016-11-29 15:00:51 +08001071 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1072 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1073 // or program object and INVALID_OPERATION if the provided name identifies an object
1074 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001075
Dian Xiang769769a2015-09-09 15:20:08 -07001076 Program *validProgram = context->getProgram(id);
1077
1078 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001079 {
Dian Xiang769769a2015-09-09 15:20:08 -07001080 if (context->getShader(id))
1081 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001083 }
1084 else
1085 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001086 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001087 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001088 }
Dian Xiang769769a2015-09-09 15:20:08 -07001089
1090 return validProgram;
1091}
1092
Jamie Madill5b772312018-03-08 20:28:32 -05001093Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001094{
1095 // See ValidProgram for spec details.
1096
1097 Shader *validShader = context->getShader(id);
1098
1099 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001100 {
Dian Xiang769769a2015-09-09 15:20:08 -07001101 if (context->getProgram(id))
1102 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001104 }
1105 else
1106 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001107 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001108 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001109 }
Dian Xiang769769a2015-09-09 15:20:08 -07001110
1111 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001112}
1113
Geoff Langb1196682014-07-23 13:47:29 -04001114bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001115{
Geoff Langfa125c92017-10-24 13:01:46 -04001116 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001117 {
Geoff Langfa125c92017-10-24 13:01:46 -04001118 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1119 {
1120 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1121 return false;
1122 }
Jamie Madillb4472272014-07-03 10:38:55 -04001123
Geoff Langfa125c92017-10-24 13:01:46 -04001124 // Color attachment 0 is validated below because it is always valid
1125 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001126 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001127 {
Geoff Langfa125c92017-10-24 13:01:46 -04001128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001129 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001130 }
1131 }
1132 else
1133 {
1134 switch (attachment)
1135 {
Geoff Langfa125c92017-10-24 13:01:46 -04001136 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001137 case GL_DEPTH_ATTACHMENT:
1138 case GL_STENCIL_ATTACHMENT:
1139 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001140
He Yunchaoced53ae2016-11-29 15:00:51 +08001141 case GL_DEPTH_STENCIL_ATTACHMENT:
1142 if (!context->getExtensions().webglCompatibility &&
1143 context->getClientMajorVersion() < 3)
1144 {
Geoff Langfa125c92017-10-24 13:01:46 -04001145 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001146 return false;
1147 }
1148 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001149
He Yunchaoced53ae2016-11-29 15:00:51 +08001150 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001151 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001152 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001153 }
1154 }
1155
1156 return true;
1157}
1158
Jamie Madill5b772312018-03-08 20:28:32 -05001159bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001160 GLenum target,
1161 GLsizei samples,
1162 GLenum internalformat,
1163 GLsizei width,
1164 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001165{
1166 switch (target)
1167 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001168 case GL_RENDERBUFFER:
1169 break;
1170 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
1175 if (width < 0 || height < 0 || samples < 0)
1176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001177 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001178 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001179 }
1180
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001181 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1182 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1183
1184 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001185 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001187 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001189 }
1190
1191 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1192 // 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 -08001193 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001194 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1195 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001196 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001197 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001198 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001199 }
1200
Geoff Langaae65a42014-05-26 12:43:44 -04001201 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001203 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001204 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001205 }
1206
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001207 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001208 if (handle == 0)
1209 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001210 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001211 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001212 }
1213
1214 return true;
1215}
1216
He Yunchaoced53ae2016-11-29 15:00:51 +08001217bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1218 GLenum target,
1219 GLenum attachment,
1220 GLenum renderbuffertarget,
1221 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001222{
Geoff Lange8afa902017-09-27 15:00:43 -04001223 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001225 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001226 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001227 }
1228
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001229 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001230
Jamie Madill84115c92015-04-23 15:00:07 -04001231 ASSERT(framebuffer);
1232 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001233 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001235 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001236 }
1237
Jamie Madillb4472272014-07-03 10:38:55 -04001238 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001239 {
Jamie Madillb4472272014-07-03 10:38:55 -04001240 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001241 }
1242
Jamie Madillab9d82c2014-01-21 16:38:14 -05001243 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1244 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1245 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1246 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1247 if (renderbuffer != 0)
1248 {
1249 if (!context->getRenderbuffer(renderbuffer))
1250 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001252 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001253 }
1254 }
1255
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001256 return true;
1257}
1258
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001259bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001260 GLint srcX0,
1261 GLint srcY0,
1262 GLint srcX1,
1263 GLint srcY1,
1264 GLint dstX0,
1265 GLint dstY0,
1266 GLint dstX1,
1267 GLint dstY1,
1268 GLbitfield mask,
1269 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270{
1271 switch (filter)
1272 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001273 case GL_NEAREST:
1274 break;
1275 case GL_LINEAR:
1276 break;
1277 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001278 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001279 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280 }
1281
1282 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001284 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001285 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001286 }
1287
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001288 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1289 // color buffer, leaving only nearest being unfiltered from above
1290 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001292 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001293 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001294 }
1295
Jamie Madill51f40ec2016-06-15 14:06:00 -04001296 const auto &glState = context->getGLState();
1297 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1298 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001299
1300 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001302 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001303 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 }
1305
Jamie Madill427064d2018-04-13 16:20:34 -04001306 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001307 {
Jamie Madill48faf802014-11-06 15:27:22 -05001308 return false;
1309 }
1310
Jamie Madill427064d2018-04-13 16:20:34 -04001311 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001312 {
Jamie Madill48faf802014-11-06 15:27:22 -05001313 return false;
1314 }
1315
Qin Jiajiaaef92162018-02-27 13:51:44 +08001316 if (readFramebuffer->id() == drawFramebuffer->id())
1317 {
1318 context->handleError(InvalidOperation());
1319 return false;
1320 }
1321
Jamie Madille98b1b52018-03-08 09:47:23 -05001322 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 {
Geoff Langb1196682014-07-23 13:47:29 -04001324 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 }
1326
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001327 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1328 // always run it in order to avoid triggering driver bugs.
1329 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1330 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001331 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001332 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1333 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001334 }
1335
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001336 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1337
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001338 if (mask & GL_COLOR_BUFFER_BIT)
1339 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001340 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001341 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001342
He Yunchao66a41a22016-12-15 16:45:05 +08001343 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001345 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001346
Geoff Langa15472a2015-08-11 11:48:03 -04001347 for (size_t drawbufferIdx = 0;
1348 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001349 {
Geoff Langa15472a2015-08-11 11:48:03 -04001350 const FramebufferAttachment *attachment =
1351 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1352 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001353 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001354 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355
Geoff Langb2f3d052013-08-13 12:49:27 -04001356 // The GL ES 3.0.2 spec (pg 193) states that:
1357 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001358 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1359 // as well
1360 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1361 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001362 // Changes with EXT_color_buffer_float:
1363 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001364 GLenum readComponentType = readFormat.info->componentType;
1365 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001366 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001367 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001368 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001369 drawComponentType == GL_SIGNED_NORMALIZED);
1370
1371 if (extensions.colorBufferFloat)
1372 {
1373 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1374 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1375
1376 if (readFixedOrFloat != drawFixedOrFloat)
1377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(InvalidOperation()
1379 << "If the read buffer contains fixed-point or "
1380 "floating-point values, the draw buffer must "
1381 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001382 return false;
1383 }
1384 }
1385 else if (readFixedPoint != drawFixedPoint)
1386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 context->handleError(InvalidOperation()
1388 << "If the read buffer contains fixed-point values, "
1389 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001390 return false;
1391 }
1392
1393 if (readComponentType == GL_UNSIGNED_INT &&
1394 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001396 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 }
1399
Jamie Madill6163c752015-12-07 16:32:59 -05001400 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001402 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001403 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 }
1405
Jamie Madilla3944d42016-07-22 22:13:26 -04001406 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001407 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001409 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001410 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
Geoff Lange4915782017-04-12 15:19:07 -04001412
1413 if (context->getExtensions().webglCompatibility &&
1414 *readColorBuffer == *attachment)
1415 {
1416 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001417 InvalidOperation()
1418 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001419 return false;
1420 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001421 }
1422 }
1423
Jamie Madilla3944d42016-07-22 22:13:26 -04001424 if ((readFormat.info->componentType == GL_INT ||
1425 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1426 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001428 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001431 }
He Yunchao66a41a22016-12-15 16:45:05 +08001432 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1433 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1434 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1435 // situation is an application error that would lead to a crash in ANGLE.
1436 else if (drawFramebuffer->hasEnabledDrawBuffer())
1437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001438 context->handleError(
1439 InvalidOperation()
1440 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001441 return false;
1442 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001443 }
1444
He Yunchaoced53ae2016-11-29 15:00:51 +08001445 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001446 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1447 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001449 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001450 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001451 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001452 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001453 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001454 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001455
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001456 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001457 {
Kenneth Russell69382852017-07-21 16:38:44 -04001458 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001460 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001461 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001462 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001463
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001464 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001465 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001466 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001467 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001468 }
Geoff Lange4915782017-04-12 15:19:07 -04001469
1470 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001472 context->handleError(
1473 InvalidOperation()
1474 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001475 return false;
1476 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001477 }
He Yunchao66a41a22016-12-15 16:45:05 +08001478 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1479 else if (drawBuffer)
1480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001481 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1482 "depth/stencil attachment of a "
1483 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001484 return false;
1485 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001486 }
1487 }
1488
Martin Radeva3ed4572017-07-27 18:29:37 +03001489 // ANGLE_multiview, Revision 1:
1490 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1491 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1492 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1493 {
1494 context->handleError(InvalidFramebufferOperation()
1495 << "Attempt to read from a multi-view framebuffer.");
1496 return false;
1497 }
1498 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1499 {
1500 context->handleError(InvalidFramebufferOperation()
1501 << "Attempt to write to a multi-view framebuffer.");
1502 return false;
1503 }
1504
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001505 return true;
1506}
1507
Jamie Madill4928b7c2017-06-20 12:57:39 -04001508bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001509 GLint x,
1510 GLint y,
1511 GLsizei width,
1512 GLsizei height,
1513 GLenum format,
1514 GLenum type,
1515 GLsizei bufSize,
1516 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001517 GLsizei *columns,
1518 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001519 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001520{
1521 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001522 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001523 return false;
1524 }
1525
Brandon Jonesd1049182018-03-28 10:02:20 -07001526 GLsizei writeLength = 0;
1527 GLsizei writeColumns = 0;
1528 GLsizei writeRows = 0;
1529
1530 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1531 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001532 {
Geoff Langb1196682014-07-23 13:47:29 -04001533 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001534 }
1535
Brandon Jonesd1049182018-03-28 10:02:20 -07001536 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001537 {
Geoff Langb1196682014-07-23 13:47:29 -04001538 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001539 }
1540
Brandon Jonesd1049182018-03-28 10:02:20 -07001541 SetRobustLengthParam(length, writeLength);
1542 SetRobustLengthParam(columns, writeColumns);
1543 SetRobustLengthParam(rows, writeRows);
1544
Jamie Madillc29968b2016-01-20 11:17:23 -05001545 return true;
1546}
1547
1548bool ValidateReadnPixelsEXT(Context *context,
1549 GLint x,
1550 GLint y,
1551 GLsizei width,
1552 GLsizei height,
1553 GLenum format,
1554 GLenum type,
1555 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001556 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001557{
1558 if (bufSize < 0)
1559 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001560 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001561 return false;
1562 }
1563
Geoff Lang62fce5b2016-09-30 10:46:35 -04001564 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001565 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001566}
Jamie Madill26e91952014-03-05 15:01:27 -05001567
Jamie Madill4928b7c2017-06-20 12:57:39 -04001568bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001569 GLint x,
1570 GLint y,
1571 GLsizei width,
1572 GLsizei height,
1573 GLenum format,
1574 GLenum type,
1575 GLsizei bufSize,
1576 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001577 GLsizei *columns,
1578 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001579 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001580{
Brandon Jonesd1049182018-03-28 10:02:20 -07001581 GLsizei writeLength = 0;
1582 GLsizei writeColumns = 0;
1583 GLsizei writeRows = 0;
1584
Geoff Lang62fce5b2016-09-30 10:46:35 -04001585 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001586 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001587 return false;
1588 }
1589
Brandon Jonesd1049182018-03-28 10:02:20 -07001590 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1591 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001592 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001593 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001594 }
1595
Brandon Jonesd1049182018-03-28 10:02:20 -07001596 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001597 {
1598 return false;
1599 }
1600
Brandon Jonesd1049182018-03-28 10:02:20 -07001601 SetRobustLengthParam(length, writeLength);
1602 SetRobustLengthParam(columns, writeColumns);
1603 SetRobustLengthParam(rows, writeRows);
1604
Geoff Lang62fce5b2016-09-30 10:46:35 -04001605 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001606}
1607
Jamie Madillf0e04492017-08-26 15:28:42 -04001608bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001609{
1610 if (!context->getExtensions().occlusionQueryBoolean &&
1611 !context->getExtensions().disjointTimerQuery)
1612 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001613 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001614 return false;
1615 }
1616
Olli Etuaho41997e72016-03-10 13:38:39 +02001617 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001618}
1619
Jamie Madillf0e04492017-08-26 15:28:42 -04001620bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001621{
1622 if (!context->getExtensions().occlusionQueryBoolean &&
1623 !context->getExtensions().disjointTimerQuery)
1624 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001625 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001626 return false;
1627 }
1628
Olli Etuaho41997e72016-03-10 13:38:39 +02001629 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001630}
1631
Jamie Madillf0e04492017-08-26 15:28:42 -04001632bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1633{
1634 if (!context->getExtensions().occlusionQueryBoolean &&
1635 !context->getExtensions().disjointTimerQuery)
1636 {
1637 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1638 return false;
1639 }
1640
1641 return true;
1642}
1643
Corentin Wallezad3ae902018-03-09 13:40:42 -05001644bool ValidateBeginQueryBase(gl::Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001645{
1646 if (!ValidQueryType(context, target))
1647 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001648 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001649 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001650 }
1651
1652 if (id == 0)
1653 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001654 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001655 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001656 }
1657
1658 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1659 // of zero, if the active query object name for <target> is non-zero (for the
1660 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1661 // the active query for either target is non-zero), if <id> is the name of an
1662 // existing query object whose type does not match <target>, or if <id> is the
1663 // active query object name for any query type, the error INVALID_OPERATION is
1664 // generated.
1665
1666 // Ensure no other queries are active
1667 // NOTE: If other queries than occlusion are supported, we will need to check
1668 // separately that:
1669 // a) The query ID passed is not the current active query for any target/type
1670 // b) There are no active queries for the requested target (and in the case
1671 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1672 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001674 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001676 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001677 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001678 }
1679
1680 Query *queryObject = context->getQuery(id, true, target);
1681
1682 // check that name was obtained with glGenQueries
1683 if (!queryObject)
1684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001685 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001686 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001687 }
1688
1689 // check for type mismatch
1690 if (queryObject->getType() != target)
1691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001692 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001693 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001694 }
1695
1696 return true;
1697}
1698
Corentin Wallezad3ae902018-03-09 13:40:42 -05001699bool ValidateBeginQueryEXT(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700{
1701 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001702 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001703 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001704 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 return false;
1706 }
1707
1708 return ValidateBeginQueryBase(context, target, id);
1709}
1710
Corentin Wallezad3ae902018-03-09 13:40:42 -05001711bool ValidateEndQueryBase(gl::Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001712{
1713 if (!ValidQueryType(context, target))
1714 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001715 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001716 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001717 }
1718
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001719 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001720
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001725 }
1726
Jamie Madill45c785d2014-05-13 14:09:34 -04001727 return true;
1728}
1729
Corentin Wallezad3ae902018-03-09 13:40:42 -05001730bool ValidateEndQueryEXT(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731{
1732 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001733 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001734 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001735 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736 return false;
1737 }
1738
1739 return ValidateEndQueryBase(context, target);
1740}
1741
Corentin Wallezad3ae902018-03-09 13:40:42 -05001742bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001743{
1744 if (!context->getExtensions().disjointTimerQuery)
1745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001746 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001747 return false;
1748 }
1749
Corentin Wallezad3ae902018-03-09 13:40:42 -05001750 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001751 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 return false;
1754 }
1755
1756 Query *queryObject = context->getQuery(id, true, target);
1757 if (queryObject == nullptr)
1758 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001759 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001760 return false;
1761 }
1762
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001763 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001764 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001765 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001766 return false;
1767 }
1768
1769 return true;
1770}
1771
Corentin Wallezad3ae902018-03-09 13:40:42 -05001772bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001773{
Geoff Lang2186c382016-10-14 10:54:54 -04001774 if (numParams)
1775 {
1776 *numParams = 0;
1777 }
1778
Corentin Wallezad3ae902018-03-09 13:40:42 -05001779 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001780 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001781 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001782 return false;
1783 }
1784
1785 switch (pname)
1786 {
1787 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001788 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001790 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001791 return false;
1792 }
1793 break;
1794 case GL_QUERY_COUNTER_BITS_EXT:
1795 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001796 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001797 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001798 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001799 return false;
1800 }
1801 break;
1802 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001803 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001804 return false;
1805 }
1806
Geoff Lang2186c382016-10-14 10:54:54 -04001807 if (numParams)
1808 {
1809 // All queries return only one value
1810 *numParams = 1;
1811 }
1812
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001813 return true;
1814}
1815
Corentin Wallezad3ae902018-03-09 13:40:42 -05001816bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001817{
1818 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001819 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001820 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001821 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001822 return false;
1823 }
1824
Geoff Lang2186c382016-10-14 10:54:54 -04001825 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001826}
1827
Geoff Lang2186c382016-10-14 10:54:54 -04001828bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001829 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001830 GLenum pname,
1831 GLsizei bufSize,
1832 GLsizei *length,
1833 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001834{
Geoff Lang2186c382016-10-14 10:54:54 -04001835 if (!ValidateRobustEntryPoint(context, bufSize))
1836 {
1837 return false;
1838 }
1839
Brandon Jonesd1049182018-03-28 10:02:20 -07001840 GLsizei numParams = 0;
1841
1842 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001843 {
1844 return false;
1845 }
1846
Brandon Jonesd1049182018-03-28 10:02:20 -07001847 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001848 {
1849 return false;
1850 }
1851
Brandon Jonesd1049182018-03-28 10:02:20 -07001852 SetRobustLengthParam(length, numParams);
1853
Geoff Lang2186c382016-10-14 10:54:54 -04001854 return true;
1855}
1856
1857bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1858{
1859 if (numParams)
1860 {
1861 *numParams = 0;
1862 }
1863
Corentin Wallezad3ae902018-03-09 13:40:42 -05001864 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865
1866 if (!queryObject)
1867 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001869 return false;
1870 }
1871
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001872 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001874 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001875 return false;
1876 }
1877
1878 switch (pname)
1879 {
1880 case GL_QUERY_RESULT_EXT:
1881 case GL_QUERY_RESULT_AVAILABLE_EXT:
1882 break;
1883
1884 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001885 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001886 return false;
1887 }
1888
Geoff Lang2186c382016-10-14 10:54:54 -04001889 if (numParams)
1890 {
1891 *numParams = 1;
1892 }
1893
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001894 return true;
1895}
1896
1897bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1898{
1899 if (!context->getExtensions().disjointTimerQuery)
1900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001901 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001902 return false;
1903 }
Geoff Lang2186c382016-10-14 10:54:54 -04001904 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1905}
1906
1907bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1908 GLuint id,
1909 GLenum pname,
1910 GLsizei bufSize,
1911 GLsizei *length,
1912 GLint *params)
1913{
1914 if (!context->getExtensions().disjointTimerQuery)
1915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001916 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001917 return false;
1918 }
1919
1920 if (!ValidateRobustEntryPoint(context, bufSize))
1921 {
1922 return false;
1923 }
1924
Brandon Jonesd1049182018-03-28 10:02:20 -07001925 GLsizei numParams = 0;
1926
1927 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001928 {
1929 return false;
1930 }
1931
Brandon Jonesd1049182018-03-28 10:02:20 -07001932 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001933 {
1934 return false;
1935 }
1936
Brandon Jonesd1049182018-03-28 10:02:20 -07001937 SetRobustLengthParam(length, numParams);
1938
Geoff Lang2186c382016-10-14 10:54:54 -04001939 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001940}
1941
1942bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1943{
1944 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001945 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001946 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001947 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001948 return false;
1949 }
Geoff Lang2186c382016-10-14 10:54:54 -04001950 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1951}
1952
1953bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1954 GLuint id,
1955 GLenum pname,
1956 GLsizei bufSize,
1957 GLsizei *length,
1958 GLuint *params)
1959{
1960 if (!context->getExtensions().disjointTimerQuery &&
1961 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001963 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001964 return false;
1965 }
1966
1967 if (!ValidateRobustEntryPoint(context, bufSize))
1968 {
1969 return false;
1970 }
1971
Brandon Jonesd1049182018-03-28 10:02:20 -07001972 GLsizei numParams = 0;
1973
1974 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001975 {
1976 return false;
1977 }
1978
Brandon Jonesd1049182018-03-28 10:02:20 -07001979 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001980 {
1981 return false;
1982 }
1983
Brandon Jonesd1049182018-03-28 10:02:20 -07001984 SetRobustLengthParam(length, numParams);
1985
Geoff Lang2186c382016-10-14 10:54:54 -04001986 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001987}
1988
1989bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1990{
1991 if (!context->getExtensions().disjointTimerQuery)
1992 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001994 return false;
1995 }
Geoff Lang2186c382016-10-14 10:54:54 -04001996 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1997}
1998
1999bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2000 GLuint id,
2001 GLenum pname,
2002 GLsizei bufSize,
2003 GLsizei *length,
2004 GLint64 *params)
2005{
2006 if (!context->getExtensions().disjointTimerQuery)
2007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002008 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002009 return false;
2010 }
2011
2012 if (!ValidateRobustEntryPoint(context, bufSize))
2013 {
2014 return false;
2015 }
2016
Brandon Jonesd1049182018-03-28 10:02:20 -07002017 GLsizei numParams = 0;
2018
2019 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002020 {
2021 return false;
2022 }
2023
Brandon Jonesd1049182018-03-28 10:02:20 -07002024 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002025 {
2026 return false;
2027 }
2028
Brandon Jonesd1049182018-03-28 10:02:20 -07002029 SetRobustLengthParam(length, numParams);
2030
Geoff Lang2186c382016-10-14 10:54:54 -04002031 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002032}
2033
2034bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2035{
2036 if (!context->getExtensions().disjointTimerQuery)
2037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002039 return false;
2040 }
Geoff Lang2186c382016-10-14 10:54:54 -04002041 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2042}
2043
2044bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2045 GLuint id,
2046 GLenum pname,
2047 GLsizei bufSize,
2048 GLsizei *length,
2049 GLuint64 *params)
2050{
2051 if (!context->getExtensions().disjointTimerQuery)
2052 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002053 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002054 return false;
2055 }
2056
2057 if (!ValidateRobustEntryPoint(context, bufSize))
2058 {
2059 return false;
2060 }
2061
Brandon Jonesd1049182018-03-28 10:02:20 -07002062 GLsizei numParams = 0;
2063
2064 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002065 {
2066 return false;
2067 }
2068
Brandon Jonesd1049182018-03-28 10:02:20 -07002069 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002070 {
2071 return false;
2072 }
2073
Brandon Jonesd1049182018-03-28 10:02:20 -07002074 SetRobustLengthParam(length, numParams);
2075
Geoff Lang2186c382016-10-14 10:54:54 -04002076 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002077}
2078
Jamie Madill5b772312018-03-08 20:28:32 -05002079bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002080 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002081 GLint location,
2082 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002083 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002084{
Jiajia Qin5451d532017-11-16 17:16:34 +08002085 // TODO(Jiajia): Add image uniform check in future.
2086 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002087 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002088 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002089 return false;
2090 }
2091
Jiajia Qin5451d532017-11-16 17:16:34 +08002092 if (!program)
2093 {
2094 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2095 return false;
2096 }
2097
2098 if (!program->isLinked())
2099 {
2100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2101 return false;
2102 }
2103
2104 if (location == -1)
2105 {
2106 // Silently ignore the uniform command
2107 return false;
2108 }
2109
2110 const auto &uniformLocations = program->getUniformLocations();
2111 size_t castedLocation = static_cast<size_t>(location);
2112 if (castedLocation >= uniformLocations.size())
2113 {
2114 context->handleError(InvalidOperation() << "Invalid uniform location");
2115 return false;
2116 }
2117
2118 const auto &uniformLocation = uniformLocations[castedLocation];
2119 if (uniformLocation.ignored)
2120 {
2121 // Silently ignore the uniform command
2122 return false;
2123 }
2124
2125 if (!uniformLocation.used())
2126 {
2127 context->handleError(InvalidOperation());
2128 return false;
2129 }
2130
2131 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2132
2133 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002134 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002135 {
2136 context->handleError(InvalidOperation());
2137 return false;
2138 }
2139
2140 *uniformOut = &uniform;
2141 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002142}
2143
Jamie Madill5b772312018-03-08 20:28:32 -05002144bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002145 GLenum uniformType,
2146 GLsizei count,
2147 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002148{
Jiajia Qin5451d532017-11-16 17:16:34 +08002149 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2150 // It is compatible with INT or BOOL.
2151 // Do these cheap tests first, for a little extra speed.
2152 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002153 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002154 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002155 }
2156
Jiajia Qin5451d532017-11-16 17:16:34 +08002157 if (IsSamplerType(uniformType))
2158 {
2159 // Check that the values are in range.
2160 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2161 for (GLsizei i = 0; i < count; ++i)
2162 {
2163 if (value[i] < 0 || value[i] >= max)
2164 {
2165 context->handleError(InvalidValue() << "sampler uniform value out of range");
2166 return false;
2167 }
2168 }
2169 return true;
2170 }
2171
2172 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2173 return false;
2174}
2175
Jamie Madill5b772312018-03-08 20:28:32 -05002176bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002177{
2178 // Check that the value type is compatible with uniform type.
2179 // Do the cheaper test first, for a little extra speed.
2180 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2181 {
2182 return true;
2183 }
2184
2185 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2186 return false;
2187}
2188
Jamie Madill5b772312018-03-08 20:28:32 -05002189bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002190{
2191 // Check that the value type is compatible with uniform type.
2192 if (valueType == uniformType)
2193 {
2194 return true;
2195 }
2196
2197 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2198 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002199}
2200
Jamie Madill5b772312018-03-08 20:28:32 -05002201bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002202{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002203 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002204 gl::Program *programObject = context->getGLState().getProgram();
2205 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2206 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002207}
2208
Jamie Madill5b772312018-03-08 20:28:32 -05002209bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002210{
2211 const LinkedUniform *uniform = nullptr;
2212 gl::Program *programObject = context->getGLState().getProgram();
2213 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2214 ValidateUniform1ivValue(context, uniform->type, count, value);
2215}
2216
Jamie Madill5b772312018-03-08 20:28:32 -05002217bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002218 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002219 GLint location,
2220 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002221 GLboolean transpose)
2222{
Geoff Lang92019432017-11-20 13:09:34 -05002223 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002225 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002226 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002227 }
2228
Jamie Madill62d31cb2015-09-11 13:25:51 -04002229 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002230 gl::Program *programObject = context->getGLState().getProgram();
2231 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2232 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002233}
2234
Jamie Madill5b772312018-03-08 20:28:32 -05002235bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002236{
2237 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002239 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002240 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002241 }
2242
Jamie Madill0af26e12015-03-05 19:54:33 -05002243 const Caps &caps = context->getCaps();
2244
Jamie Madill893ab082014-05-16 16:56:10 -04002245 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2246 {
2247 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2248
Jamie Madill0af26e12015-03-05 19:54:33 -05002249 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002251 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002252 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002253 }
2254 }
2255
2256 switch (pname)
2257 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002258 case GL_TEXTURE_BINDING_2D:
2259 case GL_TEXTURE_BINDING_CUBE_MAP:
2260 case GL_TEXTURE_BINDING_3D:
2261 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002262 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002263 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002264 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2265 if (!context->getExtensions().textureRectangle)
2266 {
2267 context->handleError(InvalidEnum()
2268 << "ANGLE_texture_rectangle extension not present");
2269 return false;
2270 }
2271 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002272 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2273 if (!context->getExtensions().eglStreamConsumerExternal &&
2274 !context->getExtensions().eglImageExternal)
2275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002276 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2277 "nor GL_OES_EGL_image_external "
2278 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002279 return false;
2280 }
2281 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002282
He Yunchaoced53ae2016-11-29 15:00:51 +08002283 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2284 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002285 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002286 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2287 ASSERT(readFramebuffer);
2288
Jamie Madill427064d2018-04-13 16:20:34 -04002289 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002290 {
Geoff Langb1196682014-07-23 13:47:29 -04002291 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002292 }
2293
Jamie Madille98b1b52018-03-08 09:47:23 -05002294 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002295 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002296 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002297 return false;
2298 }
2299
Jamie Madille98b1b52018-03-08 09:47:23 -05002300 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002301 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002303 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002304 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002305 }
2306 }
2307 break;
2308
He Yunchaoced53ae2016-11-29 15:00:51 +08002309 default:
2310 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002311 }
2312
2313 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002314 if (*numParams == 0)
2315 {
2316 return false;
2317 }
2318
2319 return true;
2320}
2321
Brandon Jonesd1049182018-03-28 10:02:20 -07002322bool ValidateGetBooleanvRobustANGLE(Context *context,
2323 GLenum pname,
2324 GLsizei bufSize,
2325 GLsizei *length,
2326 GLboolean *params)
2327{
2328 GLenum nativeType;
2329 unsigned int numParams = 0;
2330
2331 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2332 {
2333 return false;
2334 }
2335
2336 SetRobustLengthParam(length, numParams);
2337
2338 return true;
2339}
2340
2341bool ValidateGetFloatvRobustANGLE(Context *context,
2342 GLenum pname,
2343 GLsizei bufSize,
2344 GLsizei *length,
2345 GLfloat *params)
2346{
2347 GLenum nativeType;
2348 unsigned int numParams = 0;
2349
2350 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2351 {
2352 return false;
2353 }
2354
2355 SetRobustLengthParam(length, numParams);
2356
2357 return true;
2358}
2359
2360bool ValidateGetIntegervRobustANGLE(Context *context,
2361 GLenum pname,
2362 GLsizei bufSize,
2363 GLsizei *length,
2364 GLint *data)
2365{
2366 GLenum nativeType;
2367 unsigned int numParams = 0;
2368
2369 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2370 {
2371 return false;
2372 }
2373
2374 SetRobustLengthParam(length, numParams);
2375
2376 return true;
2377}
2378
2379bool ValidateGetInteger64vRobustANGLE(Context *context,
2380 GLenum pname,
2381 GLsizei bufSize,
2382 GLsizei *length,
2383 GLint64 *data)
2384{
2385 GLenum nativeType;
2386 unsigned int numParams = 0;
2387
2388 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2389 {
2390 return false;
2391 }
2392
2393 if (nativeType == GL_INT_64_ANGLEX)
2394 {
2395 CastStateValues(context, nativeType, pname, numParams, data);
2396 return false;
2397 }
2398
2399 SetRobustLengthParam(length, numParams);
2400 return true;
2401}
2402
Jamie Madill5b772312018-03-08 20:28:32 -05002403bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002404 GLenum pname,
2405 GLsizei bufSize,
2406 GLenum *nativeType,
2407 unsigned int *numParams)
2408{
2409 if (!ValidateRobustEntryPoint(context, bufSize))
2410 {
2411 return false;
2412 }
2413
2414 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2415 {
2416 return false;
2417 }
2418
2419 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002420 {
2421 return false;
2422 }
2423
2424 return true;
2425}
2426
Jamie Madill5b772312018-03-08 20:28:32 -05002427bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002428 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002429 GLint level,
2430 GLenum internalformat,
2431 bool isSubImage,
2432 GLint xoffset,
2433 GLint yoffset,
2434 GLint zoffset,
2435 GLint x,
2436 GLint y,
2437 GLsizei width,
2438 GLsizei height,
2439 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002440 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002441{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002442 TextureType texType = TextureTargetToType(target);
2443
Brandon Jones6cad5662017-06-14 13:25:13 -07002444 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002445 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002446 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2447 return false;
2448 }
2449
2450 if (width < 0 || height < 0)
2451 {
2452 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002453 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002454 }
2455
He Yunchaoced53ae2016-11-29 15:00:51 +08002456 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2457 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002459 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002460 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002461 }
2462
2463 if (border != 0)
2464 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002465 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002466 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002467 }
2468
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002469 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002471 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002472 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002473 }
2474
Jamie Madille98b1b52018-03-08 09:47:23 -05002475 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002476 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002477 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002478 {
Geoff Langb1196682014-07-23 13:47:29 -04002479 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002480 }
2481
Jamie Madille98b1b52018-03-08 09:47:23 -05002482 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002483 {
Geoff Langb1196682014-07-23 13:47:29 -04002484 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002485 }
2486
Martin Radev138064f2016-07-15 12:03:41 +03002487 if (readFramebuffer->getReadBufferState() == GL_NONE)
2488 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002489 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002490 return false;
2491 }
2492
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002493 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2494 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002495 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002496 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002497 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2498 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002499 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002500 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002501 return false;
2502 }
2503
Martin Radev04e2c3b2017-07-27 16:54:35 +03002504 // ANGLE_multiview spec, Revision 1:
2505 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2506 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2507 // is not NONE.
2508 if (source->getMultiviewLayout() != GL_NONE)
2509 {
2510 context->handleError(InvalidFramebufferOperation()
2511 << "The active read framebuffer object has multiview attachments.");
2512 return false;
2513 }
2514
Geoff Langaae65a42014-05-26 12:43:44 -04002515 const gl::Caps &caps = context->getCaps();
2516
Geoff Langaae65a42014-05-26 12:43:44 -04002517 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002518 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002519 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002520 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002521 maxDimension = caps.max2DTextureSize;
2522 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002523
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002524 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002525 maxDimension = caps.maxCubeMapTextureSize;
2526 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002527
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002528 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002529 maxDimension = caps.maxRectangleTextureSize;
2530 break;
2531
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002532 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002533 maxDimension = caps.max2DTextureSize;
2534 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002535
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002536 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002537 maxDimension = caps.max3DTextureSize;
2538 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002539
He Yunchaoced53ae2016-11-29 15:00:51 +08002540 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002541 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002542 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002543 }
2544
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002545 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002546 if (!texture)
2547 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002548 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002549 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002550 }
2551
Geoff Lang69cce582015-09-17 13:20:36 -04002552 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002554 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002555 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002556 }
2557
Geoff Langca271392017-04-05 12:30:00 -04002558 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002559 isSubImage ? *texture->getFormat(target, level).info
2560 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002561
Geoff Lang966c9402017-04-18 12:38:27 -04002562 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002564 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002565 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002566 }
2567
2568 if (isSubImage)
2569 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002570 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2571 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2572 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002574 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002575 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002576 }
2577 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002578 else
2579 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002580 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002581 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002582 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002583 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002584 }
2585
Geoff Langeb66a6e2016-10-31 13:06:12 -04002586 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002587 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002588 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002589 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002590 }
2591
2592 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002593 if (static_cast<int>(width) > maxLevelDimension ||
2594 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002595 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002596 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002597 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002598 }
2599 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002600
Jamie Madill0c8abca2016-07-22 20:21:26 -04002601 if (textureFormatOut)
2602 {
2603 *textureFormatOut = texture->getFormat(target, level);
2604 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002605
2606 // Detect texture copying feedback loops for WebGL.
2607 if (context->getExtensions().webglCompatibility)
2608 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002609 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002610 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002611 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002612 return false;
2613 }
2614 }
2615
Jamie Madill560a8d82014-05-21 13:06:20 -04002616 return true;
2617}
2618
Jamie Madill5b772312018-03-08 20:28:32 -05002619bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002620{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002621 const Extensions &extensions = context->getExtensions();
2622
Jamie Madill1aeb1312014-06-20 13:21:25 -04002623 switch (mode)
2624 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002625 case GL_POINTS:
2626 case GL_LINES:
2627 case GL_LINE_LOOP:
2628 case GL_LINE_STRIP:
2629 case GL_TRIANGLES:
2630 case GL_TRIANGLE_STRIP:
2631 case GL_TRIANGLE_FAN:
2632 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002633
2634 case GL_LINES_ADJACENCY_EXT:
2635 case GL_LINE_STRIP_ADJACENCY_EXT:
2636 case GL_TRIANGLES_ADJACENCY_EXT:
2637 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2638 if (!extensions.geometryShader)
2639 {
2640 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2641 return false;
2642 }
2643 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002644 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002645 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002646 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002647 }
2648
Jamie Madill250d33f2014-06-06 17:09:03 -04002649 if (count < 0)
2650 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002651 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002652 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002653 }
2654
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002655 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002656
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002657 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2658 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2659 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2660 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002661 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002662 // Check for mapped buffers
2663 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002664 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002665 {
2666 context->handleError(InvalidOperation());
2667 return false;
2668 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002669 }
2670
Jamie Madillcbcde722017-01-06 14:50:00 -05002671 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2672 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002673 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002674 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002675 {
Ken Russellb9f92502018-01-27 19:00:26 -08002676 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002677 const FramebufferAttachment *dsAttachment =
2678 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002679 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2680 ASSERT(stencilBits <= 8);
2681
Jinyoung Hur85769f02015-10-20 17:08:44 -04002682 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002683 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002684 {
Ken Russellb9f92502018-01-27 19:00:26 -08002685 GLuint maxStencilValue = (1 << stencilBits) - 1;
2686
2687 bool differentRefs =
2688 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2689 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2690 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2691 (depthStencilState.stencilBackWritemask & maxStencilValue);
2692 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2693 (depthStencilState.stencilBackMask & maxStencilValue);
2694
2695 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002696 {
Ken Russellb9f92502018-01-27 19:00:26 -08002697 if (!extensions.webglCompatibility)
2698 {
2699 ERR() << "This ANGLE implementation does not support separate front/back "
2700 "stencil writemasks, reference values, or stencil mask values.";
2701 }
2702 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2703 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002704 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002705 }
Jamie Madillac528012014-06-20 13:21:23 -04002706 }
2707
Jamie Madill427064d2018-04-13 16:20:34 -04002708 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002709 {
Geoff Langb1196682014-07-23 13:47:29 -04002710 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002711 }
2712
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002713 // If we are running GLES1, there is no current program.
2714 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002715 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002716
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002717 gl::Program *program = state.getProgram();
2718 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002719 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002720 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002721 return false;
2722 }
Martin Radev7e69f762017-07-27 14:54:13 +03002723
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002724 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2725 // vertex shader stage or fragment shader stage is a undefined behaviour.
2726 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2727 // produce undefined result.
2728 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2729 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002730 {
2731 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002732 << "It is a undefined behaviour to render without "
2733 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002734 return false;
2735 }
Martin Radevffe754b2017-07-31 10:38:07 +03002736
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002737 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002738 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002739 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002740 return false;
2741 }
2742
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002743 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002744 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002745 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2746 const int framebufferNumViews = framebuffer->getNumViews();
2747 if (framebufferNumViews != programNumViews)
2748 {
2749 context->handleError(InvalidOperation()
2750 << "The number of views in the active program "
2751 "and draw framebuffer does not match.");
2752 return false;
2753 }
2754
2755 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2756 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2757 framebufferNumViews > 1)
2758 {
2759 context->handleError(InvalidOperation()
2760 << "There is an active transform feedback object "
2761 "when the number of views in the active draw "
2762 "framebuffer is greater than 1.");
2763 return false;
2764 }
2765
2766 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2767 state.isQueryActive(QueryType::TimeElapsed))
2768 {
2769 context->handleError(InvalidOperation()
2770 << "There is an active query for target "
2771 "GL_TIME_ELAPSED_EXT when the number of "
2772 "views in the active draw framebuffer is "
2773 "greater than 1.");
2774 return false;
2775 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002776 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002777
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002778 // Do geometry shader specific validations
2779 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002780 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002781 if (!IsCompatibleDrawModeWithGeometryShader(
2782 mode, program->getGeometryShaderInputPrimitiveType()))
2783 {
2784 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2785 IncompatibleDrawModeAgainstGeometryShader);
2786 return false;
2787 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002788 }
Geoff Lange0cff192017-05-30 13:04:56 -04002789
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002790 // Uniform buffer validation
2791 for (unsigned int uniformBlockIndex = 0;
2792 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002793 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002794 const gl::InterfaceBlock &uniformBlock =
2795 program->getUniformBlockByIndex(uniformBlockIndex);
2796 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2797 const OffsetBindingPointer<Buffer> &uniformBuffer =
2798 state.getIndexedUniformBuffer(blockBinding);
2799
2800 if (uniformBuffer.get() == nullptr)
2801 {
2802 // undefined behaviour
2803 context->handleError(
2804 InvalidOperation()
2805 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2806 return false;
2807 }
2808
2809 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2810 if (uniformBufferSize < uniformBlock.dataSize)
2811 {
2812 // undefined behaviour
2813 context->handleError(
2814 InvalidOperation()
2815 << "It is undefined behaviour to use a uniform buffer that is too small.");
2816 return false;
2817 }
2818
2819 if (extensions.webglCompatibility &&
2820 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2821 {
2822 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2823 UniformBufferBoundForTransformFeedback);
2824 return false;
2825 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002826 }
2827
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002828 // Do some additonal WebGL-specific validation
2829 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002830 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002831 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2832 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2833 transformFeedbackObject->buffersBoundForOtherUse())
2834 {
2835 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2836 TransformFeedbackBufferDoubleBound);
2837 return false;
2838 }
2839 // Detect rendering feedback loops for WebGL.
2840 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2841 {
2842 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2843 return false;
2844 }
2845
2846 // Detect that the vertex shader input types match the attribute types
2847 if (!ValidateVertexShaderAttributeTypeMatch(context))
2848 {
2849 return false;
2850 }
2851
2852 // Detect that the color buffer types match the fragment shader output types
2853 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2854 {
2855 return false;
2856 }
Geoff Lange0cff192017-05-30 13:04:56 -04002857 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002858 }
2859
Jamie Madill9fdaa492018-02-16 10:52:11 -05002860 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002861}
2862
Jamie Madill5b772312018-03-08 20:28:32 -05002863bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002864 GLenum mode,
2865 GLint first,
2866 GLsizei count,
2867 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002868{
Jamie Madillfd716582014-06-06 17:09:04 -04002869 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002870 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002871 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002872 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002873 }
2874
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002875 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002876 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002877 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002878 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002879 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002880 if (!ValidateTransformFeedbackPrimitiveMode(context,
2881 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002882 {
James Darpinian30b604d2018-03-12 17:26:57 -07002883 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2884 return false;
2885 }
2886
2887 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2888 {
2889 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2890 return false;
2891 }
Jamie Madillfd716582014-06-06 17:09:04 -04002892 }
2893
Jiajia Qind9671222016-11-29 16:30:31 +08002894 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002895 {
2896 return false;
2897 }
2898
Corentin Wallez71168a02016-12-19 15:11:18 -08002899 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002900 // - first < 0 has been checked as an error condition.
2901 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002902 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002903 ASSERT(first >= 0);
2904 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002905 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002906 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2907 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2908 {
2909 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2910 return false;
2911 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002912
Jamie Madill9fdaa492018-02-16 10:52:11 -05002913 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2914 {
2915 return false;
2916 }
Jamie Madillfd716582014-06-06 17:09:04 -04002917 }
2918
2919 return true;
2920}
2921
He Yunchaoced53ae2016-11-29 15:00:51 +08002922bool ValidateDrawArraysInstancedANGLE(Context *context,
2923 GLenum mode,
2924 GLint first,
2925 GLsizei count,
2926 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002927{
Geoff Lang63c5a592017-09-27 14:08:16 -04002928 if (!context->getExtensions().instancedArrays)
2929 {
2930 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2931 return false;
2932 }
2933
Corentin Wallez170efbf2017-05-02 13:45:01 -04002934 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002935 {
2936 return false;
2937 }
2938
Corentin Wallez0dc97812017-06-22 14:38:44 -04002939 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002940}
2941
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002942bool ValidateDrawElementsBase(Context *context, GLenum mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002943{
Jamie Madill250d33f2014-06-06 17:09:03 -04002944 switch (type)
2945 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002946 case GL_UNSIGNED_BYTE:
2947 case GL_UNSIGNED_SHORT:
2948 break;
2949 case GL_UNSIGNED_INT:
2950 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2951 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002952 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002953 return false;
2954 }
2955 break;
2956 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002958 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002959 }
2960
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002961 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002962
2963 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002964 if (curTransformFeedback && curTransformFeedback->isActive() &&
2965 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002966 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002967 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2968 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2969 if (context->getExtensions().geometryShader)
2970 {
2971 if (!ValidateTransformFeedbackPrimitiveMode(
2972 context, curTransformFeedback->getPrimitiveMode(), mode))
2973 {
2974 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2975 return false;
2976 }
2977 }
2978 else
2979 {
2980 // It is an invalid operation to call DrawElements, DrawRangeElements or
2981 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2982 // 86)
2983 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2984 UnsupportedDrawModeForTransformFeedback);
2985 return false;
2986 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002987 }
2988
Jiajia Qind9671222016-11-29 16:30:31 +08002989 return true;
2990}
2991
Jamie Madill5b772312018-03-08 20:28:32 -05002992bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002993 GLenum mode,
2994 GLsizei count,
2995 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002996 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002997 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002998{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002999 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003000 return false;
3001
3002 const State &state = context->getGLState();
3003
Corentin Wallez170efbf2017-05-02 13:45:01 -04003004 if (!ValidateDrawBase(context, mode, count))
3005 {
3006 return false;
3007 }
3008
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003009 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
3010 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3011 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3012 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04003013 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003014 // Check for mapped buffers
3015 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04003016 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003017 {
3018 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3019 return false;
3020 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003021 }
3022
He Yunchaoced53ae2016-11-29 15:00:51 +08003023 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003024 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003025
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003026 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3027
3028 if (context->getExtensions().webglCompatibility)
3029 {
3030 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3031 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3032 {
3033 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3034 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3035 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003036 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003037 return false;
3038 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003039
3040 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3041 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3042 // error is generated.
3043 if (reinterpret_cast<intptr_t>(indices) < 0)
3044 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003045 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003046 return false;
3047 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003048 }
3049
3050 if (context->getExtensions().webglCompatibility ||
3051 !context->getGLState().areClientArraysEnabled())
3052 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003053 if (!elementArrayBuffer && count > 0)
3054 {
3055 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3056 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3057 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003058 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003059 return false;
3060 }
3061 }
3062
Jamie Madill9fdaa492018-02-16 10:52:11 -05003063 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003064 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003065 // This is an application error that would normally result in a crash, but we catch it and
3066 // return an error
3067 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3068 return false;
3069 }
3070
3071 if (count > 0 && elementArrayBuffer)
3072 {
3073 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3074 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3075 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3076 constexpr uint64_t kMaxTypeSize = 8;
3077 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3078 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3079 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3080
3081 uint64_t typeSize = typeBytes;
3082 uint64_t elementCount = static_cast<uint64_t>(count);
3083 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3084
3085 // Doing the multiplication here is overflow-safe
3086 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3087
3088 // The offset can be any value, check for overflows
3089 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3090 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003091 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003092 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3093 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003094 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003095
3096 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3097 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003098 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003099 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3100 return false;
3101 }
3102
3103 ASSERT(isPow2(typeSize) && typeSize > 0);
3104 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3105 {
3106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003107 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003108 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003109
3110 if (context->getExtensions().webglCompatibility &&
3111 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3112 {
3113 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3114 ElementArrayBufferBoundForTransformFeedback);
3115 return false;
3116 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003117 }
3118
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003119 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003120 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003121 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3122 // access is enabled.
3123 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3124 {
3125 return false;
3126 }
3127 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003128 else if (count == 0)
3129 {
3130 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3131 // count.
3132 if (!ValidateDrawAttribs(context, 0, 0, 0))
3133 {
3134 return false;
3135 }
3136 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003137 else
3138 {
3139 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003140 const DrawCallParams &params = context->getParams<DrawCallParams>();
3141 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3142 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003143
3144 // If we use an index greater than our maximum supported index range, return an error.
3145 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3146 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003147 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003148 {
3149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3150 return false;
3151 }
3152
Jamie Madill6f5444d2018-03-14 10:08:11 -04003153 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3154 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003155 {
3156 return false;
3157 }
3158
3159 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003160 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003161 }
3162
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003163 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003164}
3165
Jamie Madill5b772312018-03-08 20:28:32 -05003166bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003167 GLenum mode,
3168 GLsizei count,
3169 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003170 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003171 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003172{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003173 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003174}
3175
Geoff Lang3edfe032015-09-04 16:38:24 -04003176bool ValidateDrawElementsInstancedANGLE(Context *context,
3177 GLenum mode,
3178 GLsizei count,
3179 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003180 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003181 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003182{
Geoff Lang63c5a592017-09-27 14:08:16 -04003183 if (!context->getExtensions().instancedArrays)
3184 {
3185 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3186 return false;
3187 }
3188
Corentin Wallez170efbf2017-05-02 13:45:01 -04003189 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003190 {
3191 return false;
3192 }
3193
Corentin Wallez0dc97812017-06-22 14:38:44 -04003194 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003195}
3196
He Yunchaoced53ae2016-11-29 15:00:51 +08003197bool ValidateFramebufferTextureBase(Context *context,
3198 GLenum target,
3199 GLenum attachment,
3200 GLuint texture,
3201 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003202{
Geoff Lange8afa902017-09-27 15:00:43 -04003203 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003204 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003205 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003206 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003207 }
3208
3209 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003210 {
3211 return false;
3212 }
3213
Jamie Madill55ec3b12014-07-03 10:38:57 -04003214 if (texture != 0)
3215 {
3216 gl::Texture *tex = context->getTexture(texture);
3217
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003218 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003220 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003221 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003222 }
3223
3224 if (level < 0)
3225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003226 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003227 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003228 }
3229 }
3230
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003231 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003232 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003233
Jamie Madill84115c92015-04-23 15:00:07 -04003234 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003235 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003236 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003237 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003238 }
3239
3240 return true;
3241}
3242
Geoff Langb1196682014-07-23 13:47:29 -04003243bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003244{
3245 if (program == 0)
3246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003247 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003248 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003249 }
3250
Dian Xiang769769a2015-09-09 15:20:08 -07003251 gl::Program *programObject = GetValidProgram(context, program);
3252 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003253 {
3254 return false;
3255 }
3256
Jamie Madill0063c512014-08-25 15:47:53 -04003257 if (!programObject || !programObject->isLinked())
3258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003259 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003260 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003261 }
3262
Geoff Lang7dd2e102014-11-10 15:19:26 -05003263 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003265 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003266 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003267 }
3268
Jamie Madill0063c512014-08-25 15:47:53 -04003269 return true;
3270}
3271
Geoff Langf41d0ee2016-10-07 13:04:23 -04003272static bool ValidateSizedGetUniform(Context *context,
3273 GLuint program,
3274 GLint location,
3275 GLsizei bufSize,
3276 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003277{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003278 if (length)
3279 {
3280 *length = 0;
3281 }
3282
Jamie Madill78f41802014-08-25 15:47:55 -04003283 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003284 {
Jamie Madill78f41802014-08-25 15:47:55 -04003285 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003286 }
3287
Geoff Langf41d0ee2016-10-07 13:04:23 -04003288 if (bufSize < 0)
3289 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003290 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003291 return false;
3292 }
3293
Jamie Madilla502c742014-08-28 17:19:13 -04003294 gl::Program *programObject = context->getProgram(program);
3295 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003296
Jamie Madill78f41802014-08-25 15:47:55 -04003297 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003298 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003299 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003300 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003301 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003302 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003303 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003304 }
3305
Geoff Langf41d0ee2016-10-07 13:04:23 -04003306 if (length)
3307 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003308 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003309 }
3310
Jamie Madill0063c512014-08-25 15:47:53 -04003311 return true;
3312}
3313
He Yunchaoced53ae2016-11-29 15:00:51 +08003314bool ValidateGetnUniformfvEXT(Context *context,
3315 GLuint program,
3316 GLint location,
3317 GLsizei bufSize,
3318 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003319{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003320 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003321}
3322
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003323bool ValidateGetnUniformfvRobustANGLE(Context *context,
3324 GLuint program,
3325 GLint location,
3326 GLsizei bufSize,
3327 GLsizei *length,
3328 GLfloat *params)
3329{
3330 UNIMPLEMENTED();
3331 return false;
3332}
3333
He Yunchaoced53ae2016-11-29 15:00:51 +08003334bool ValidateGetnUniformivEXT(Context *context,
3335 GLuint program,
3336 GLint location,
3337 GLsizei bufSize,
3338 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003339{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003340 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3341}
3342
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003343bool ValidateGetnUniformivRobustANGLE(Context *context,
3344 GLuint program,
3345 GLint location,
3346 GLsizei bufSize,
3347 GLsizei *length,
3348 GLint *params)
3349{
3350 UNIMPLEMENTED();
3351 return false;
3352}
3353
3354bool ValidateGetnUniformuivRobustANGLE(Context *context,
3355 GLuint program,
3356 GLint location,
3357 GLsizei bufSize,
3358 GLsizei *length,
3359 GLuint *params)
3360{
3361 UNIMPLEMENTED();
3362 return false;
3363}
3364
Geoff Langf41d0ee2016-10-07 13:04:23 -04003365bool ValidateGetUniformfvRobustANGLE(Context *context,
3366 GLuint program,
3367 GLint location,
3368 GLsizei bufSize,
3369 GLsizei *length,
3370 GLfloat *params)
3371{
3372 if (!ValidateRobustEntryPoint(context, bufSize))
3373 {
3374 return false;
3375 }
3376
Brandon Jonesd1049182018-03-28 10:02:20 -07003377 GLsizei writeLength = 0;
3378
Geoff Langf41d0ee2016-10-07 13:04:23 -04003379 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003380 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3381 {
3382 return false;
3383 }
3384
3385 SetRobustLengthParam(length, writeLength);
3386
3387 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003388}
3389
3390bool ValidateGetUniformivRobustANGLE(Context *context,
3391 GLuint program,
3392 GLint location,
3393 GLsizei bufSize,
3394 GLsizei *length,
3395 GLint *params)
3396{
3397 if (!ValidateRobustEntryPoint(context, bufSize))
3398 {
3399 return false;
3400 }
3401
Brandon Jonesd1049182018-03-28 10:02:20 -07003402 GLsizei writeLength = 0;
3403
Geoff Langf41d0ee2016-10-07 13:04:23 -04003404 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003405 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3406 {
3407 return false;
3408 }
3409
3410 SetRobustLengthParam(length, writeLength);
3411
3412 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003413}
3414
3415bool ValidateGetUniformuivRobustANGLE(Context *context,
3416 GLuint program,
3417 GLint location,
3418 GLsizei bufSize,
3419 GLsizei *length,
3420 GLuint *params)
3421{
3422 if (!ValidateRobustEntryPoint(context, bufSize))
3423 {
3424 return false;
3425 }
3426
3427 if (context->getClientMajorVersion() < 3)
3428 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003429 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003430 return false;
3431 }
3432
Brandon Jonesd1049182018-03-28 10:02:20 -07003433 GLsizei writeLength = 0;
3434
Geoff Langf41d0ee2016-10-07 13:04:23 -04003435 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003436 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3437 {
3438 return false;
3439 }
3440
3441 SetRobustLengthParam(length, writeLength);
3442
3443 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003444}
3445
He Yunchaoced53ae2016-11-29 15:00:51 +08003446bool ValidateDiscardFramebufferBase(Context *context,
3447 GLenum target,
3448 GLsizei numAttachments,
3449 const GLenum *attachments,
3450 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003451{
3452 if (numAttachments < 0)
3453 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003454 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003455 return false;
3456 }
3457
3458 for (GLsizei i = 0; i < numAttachments; ++i)
3459 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003460 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003461 {
3462 if (defaultFramebuffer)
3463 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003464 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003465 return false;
3466 }
3467
3468 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003470 context->handleError(InvalidOperation() << "Requested color attachment is "
3471 "greater than the maximum supported "
3472 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003473 return false;
3474 }
3475 }
3476 else
3477 {
3478 switch (attachments[i])
3479 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003480 case GL_DEPTH_ATTACHMENT:
3481 case GL_STENCIL_ATTACHMENT:
3482 case GL_DEPTH_STENCIL_ATTACHMENT:
3483 if (defaultFramebuffer)
3484 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003485 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3486 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003487 return false;
3488 }
3489 break;
3490 case GL_COLOR:
3491 case GL_DEPTH:
3492 case GL_STENCIL:
3493 if (!defaultFramebuffer)
3494 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003495 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3496 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003497 return false;
3498 }
3499 break;
3500 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003501 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003502 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003503 }
3504 }
3505 }
3506
3507 return true;
3508}
3509
Austin Kinross6ee1e782015-05-29 17:05:37 -07003510bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3511{
Jamie Madill007530e2017-12-28 14:27:04 -05003512 if (!context->getExtensions().debugMarker)
3513 {
3514 // The debug marker calls should not set error state
3515 // However, it seems reasonable to set an error state if the extension is not enabled
3516 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3517 return false;
3518 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003519
Jamie Madill007530e2017-12-28 14:27:04 -05003520 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003521 if (length < 0)
3522 {
3523 return false;
3524 }
3525
3526 if (marker == nullptr)
3527 {
3528 return false;
3529 }
3530
3531 return true;
3532}
3533
3534bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3535{
Jamie Madill007530e2017-12-28 14:27:04 -05003536 if (!context->getExtensions().debugMarker)
3537 {
3538 // The debug marker calls should not set error state
3539 // However, it seems reasonable to set an error state if the extension is not enabled
3540 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3541 return false;
3542 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003543
Jamie Madill007530e2017-12-28 14:27:04 -05003544 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003545 if (length < 0)
3546 {
3547 return false;
3548 }
3549
3550 if (length > 0 && marker == nullptr)
3551 {
3552 return false;
3553 }
3554
3555 return true;
3556}
3557
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003558bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003559{
Geoff Langa8406172015-07-21 16:53:39 -04003560 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003562 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003563 return false;
3564 }
3565
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003566 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003567 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003568 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003569 if (!context->getExtensions().eglImage)
3570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003571 context->handleError(InvalidEnum()
3572 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003573 }
3574 break;
3575
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003576 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003577 if (!context->getExtensions().eglImageExternal)
3578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003579 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3580 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003581 }
Geoff Langa8406172015-07-21 16:53:39 -04003582 break;
3583
3584 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003585 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003586 return false;
3587 }
3588
Jamie Madill007530e2017-12-28 14:27:04 -05003589 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3590
Jamie Madill61e16b42017-06-19 11:13:23 -04003591 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003592 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003594 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003595 return false;
3596 }
3597
Jamie Madill007530e2017-12-28 14:27:04 -05003598 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003600 context->handleError(InvalidOperation()
3601 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003602 return false;
3603 }
3604
Geoff Langca271392017-04-05 12:30:00 -04003605 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003606 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003607 if (!textureCaps.texturable)
3608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003609 context->handleError(InvalidOperation()
3610 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003611 return false;
3612 }
3613
Geoff Langdcab33b2015-07-21 13:03:16 -04003614 return true;
3615}
3616
3617bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003618 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003619 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003620{
Geoff Langa8406172015-07-21 16:53:39 -04003621 if (!context->getExtensions().eglImage)
3622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003623 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003624 return false;
3625 }
3626
3627 switch (target)
3628 {
3629 case GL_RENDERBUFFER:
3630 break;
3631
3632 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003633 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003634 return false;
3635 }
3636
Jamie Madill007530e2017-12-28 14:27:04 -05003637 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3638
Jamie Madill61e16b42017-06-19 11:13:23 -04003639 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003640 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003641 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003642 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003643 return false;
3644 }
3645
Geoff Langca271392017-04-05 12:30:00 -04003646 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003647 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003648 if (!textureCaps.renderable)
3649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003650 context->handleError(InvalidOperation()
3651 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003652 return false;
3653 }
3654
Geoff Langdcab33b2015-07-21 13:03:16 -04003655 return true;
3656}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003657
3658bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3659{
Geoff Lang36167ab2015-12-07 10:27:14 -05003660 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003661 {
3662 // The default VAO should always exist
3663 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003664 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003665 return false;
3666 }
3667
3668 return true;
3669}
3670
Geoff Langc5629752015-12-07 16:29:04 -05003671bool ValidateProgramBinaryBase(Context *context,
3672 GLuint program,
3673 GLenum binaryFormat,
3674 const void *binary,
3675 GLint length)
3676{
3677 Program *programObject = GetValidProgram(context, program);
3678 if (programObject == nullptr)
3679 {
3680 return false;
3681 }
3682
3683 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3684 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3685 programBinaryFormats.end())
3686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003687 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003688 return false;
3689 }
3690
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003691 if (context->hasActiveTransformFeedback(program))
3692 {
3693 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003694 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3695 "is associated with an active transform "
3696 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003697 return false;
3698 }
3699
Geoff Langc5629752015-12-07 16:29:04 -05003700 return true;
3701}
3702
3703bool ValidateGetProgramBinaryBase(Context *context,
3704 GLuint program,
3705 GLsizei bufSize,
3706 GLsizei *length,
3707 GLenum *binaryFormat,
3708 void *binary)
3709{
3710 Program *programObject = GetValidProgram(context, program);
3711 if (programObject == nullptr)
3712 {
3713 return false;
3714 }
3715
3716 if (!programObject->isLinked())
3717 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003719 return false;
3720 }
3721
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003722 if (context->getCaps().programBinaryFormats.empty())
3723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003724 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003725 return false;
3726 }
3727
Geoff Langc5629752015-12-07 16:29:04 -05003728 return true;
3729}
Jamie Madillc29968b2016-01-20 11:17:23 -05003730
Jamie Madill5b772312018-03-08 20:28:32 -05003731bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003732{
3733 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003734 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003735 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003736 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3737 return false;
3738 }
3739 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3740 {
3741 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003742 return false;
3743 }
3744
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003745 ASSERT(context->getGLState().getDrawFramebuffer());
3746 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003747 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3748
3749 // This should come first before the check for the default frame buffer
3750 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3751 // rather than INVALID_OPERATION
3752 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3753 {
3754 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3755
3756 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003757 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3758 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003759 {
3760 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003761 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3762 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3763 // 3.1 is still a bit ambiguous about the error, but future specs are
3764 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003765 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003766 return false;
3767 }
3768 else if (bufs[colorAttachment] >= maxColorAttachment)
3769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003770 context->handleError(InvalidOperation()
3771 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003772 return false;
3773 }
3774 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3775 frameBufferId != 0)
3776 {
3777 // INVALID_OPERATION-GL is bound to buffer and ith argument
3778 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003779 context->handleError(InvalidOperation()
3780 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003781 return false;
3782 }
3783 }
3784
3785 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3786 // and n is not 1 or bufs is bound to value other than BACK and NONE
3787 if (frameBufferId == 0)
3788 {
3789 if (n != 1)
3790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003791 context->handleError(InvalidOperation()
3792 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003793 return false;
3794 }
3795
3796 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003798 context->handleError(
3799 InvalidOperation()
3800 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003801 return false;
3802 }
3803 }
3804
3805 return true;
3806}
3807
Geoff Lang496c02d2016-10-20 11:38:11 -07003808bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003809 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003810 GLenum pname,
3811 GLsizei *length,
3812 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003813{
Geoff Lang496c02d2016-10-20 11:38:11 -07003814 if (length)
3815 {
3816 *length = 0;
3817 }
3818
3819 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3820 {
3821 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003822 InvalidOperation()
3823 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003824 return false;
3825 }
3826
Corentin Walleze4477002017-12-01 14:39:58 -05003827 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003828 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003829 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003830 return false;
3831 }
3832
Geoff Lang496c02d2016-10-20 11:38:11 -07003833 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003834 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003835 case GL_BUFFER_MAP_POINTER:
3836 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003837
Geoff Lang496c02d2016-10-20 11:38:11 -07003838 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003839 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003840 return false;
3841 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003842
3843 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3844 // target bound to zero generate an INVALID_OPERATION error."
3845 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003846 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003848 context->handleError(InvalidOperation()
3849 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003850 return false;
3851 }
3852
Geoff Lang496c02d2016-10-20 11:38:11 -07003853 if (length)
3854 {
3855 *length = 1;
3856 }
3857
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 return true;
3859}
3860
Corentin Wallez336129f2017-10-17 15:55:40 -04003861bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003862{
Corentin Walleze4477002017-12-01 14:39:58 -05003863 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003864 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003865 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003866 return false;
3867 }
3868
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003869 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003870
3871 if (buffer == nullptr || !buffer->isMapped())
3872 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003873 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003874 return false;
3875 }
3876
3877 return true;
3878}
3879
3880bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003881 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 GLintptr offset,
3883 GLsizeiptr length,
3884 GLbitfield access)
3885{
Corentin Walleze4477002017-12-01 14:39:58 -05003886 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003887 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003888 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003889 return false;
3890 }
3891
Brandon Jones6cad5662017-06-14 13:25:13 -07003892 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003893 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003894 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3895 return false;
3896 }
3897
3898 if (length < 0)
3899 {
3900 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003901 return false;
3902 }
3903
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003904 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003905
3906 if (!buffer)
3907 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003908 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003909 return false;
3910 }
3911
3912 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003913 CheckedNumeric<size_t> checkedOffset(offset);
3914 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003915
Jamie Madille2e406c2016-06-02 13:04:10 -04003916 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003918 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003919 return false;
3920 }
3921
3922 // Check for invalid bits in the mask
3923 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3924 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3925 GL_MAP_UNSYNCHRONIZED_BIT;
3926
3927 if (access & ~(allAccessBits))
3928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003929 context->handleError(InvalidValue()
3930 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003931 return false;
3932 }
3933
3934 if (length == 0)
3935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003936 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003937 return false;
3938 }
3939
3940 if (buffer->isMapped())
3941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003942 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003943 return false;
3944 }
3945
3946 // Check for invalid bit combinations
3947 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003949 context->handleError(InvalidOperation()
3950 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003951 return false;
3952 }
3953
3954 GLbitfield writeOnlyBits =
3955 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3956
3957 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003959 context->handleError(InvalidOperation()
3960 << "Invalid access bits when mapping buffer for reading: 0x"
3961 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003962 return false;
3963 }
3964
3965 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003967 context->handleError(
3968 InvalidOperation()
3969 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003970 return false;
3971 }
Geoff Lang79f71042017-08-14 16:43:43 -04003972
3973 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003974}
3975
3976bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003977 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003978 GLintptr offset,
3979 GLsizeiptr length)
3980{
Brandon Jones6cad5662017-06-14 13:25:13 -07003981 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003982 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003983 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3984 return false;
3985 }
3986
3987 if (length < 0)
3988 {
3989 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003990 return false;
3991 }
3992
Corentin Walleze4477002017-12-01 14:39:58 -05003993 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003994 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003995 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003996 return false;
3997 }
3998
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003999 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004000
4001 if (buffer == nullptr)
4002 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004003 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004004 return false;
4005 }
4006
4007 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004009 context->handleError(InvalidOperation()
4010 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004011 return false;
4012 }
4013
4014 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004015 CheckedNumeric<size_t> checkedOffset(offset);
4016 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004017
Jamie Madille2e406c2016-06-02 13:04:10 -04004018 if (!checkedSize.IsValid() ||
4019 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004021 context->handleError(InvalidValue()
4022 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004023 return false;
4024 }
4025
4026 return true;
4027}
4028
Olli Etuaho41997e72016-03-10 13:38:39 +02004029bool ValidateGenOrDelete(Context *context, GLint n)
4030{
4031 if (n < 0)
4032 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004033 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004034 return false;
4035 }
4036 return true;
4037}
4038
Jamie Madill5b772312018-03-08 20:28:32 -05004039bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004040{
4041 if (!context->getExtensions().robustClientMemory)
4042 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004043 context->handleError(InvalidOperation()
4044 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004045 return false;
4046 }
4047
4048 if (bufSize < 0)
4049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004050 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004051 return false;
4052 }
4053
4054 return true;
4055}
4056
Jamie Madill5b772312018-03-08 20:28:32 -05004057bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004058{
4059 if (bufSize < numParams)
4060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004061 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4062 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004063 return false;
4064 }
4065
4066 return true;
4067}
4068
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004069bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004070 GLenum target,
4071 GLenum attachment,
4072 GLenum pname,
4073 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004074{
Geoff Lange8afa902017-09-27 15:00:43 -04004075 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004077 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004078 return false;
4079 }
4080
4081 int clientVersion = context->getClientMajorVersion();
4082
4083 switch (pname)
4084 {
4085 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4086 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4087 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4088 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4089 break;
4090
Martin Radeve5285d22017-07-14 16:23:53 +03004091 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4092 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4093 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4094 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4095 if (clientVersion < 3 || !context->getExtensions().multiview)
4096 {
4097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4098 return false;
4099 }
4100 break;
4101
Geoff Langff5b2d52016-09-07 11:32:23 -04004102 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4103 if (clientVersion < 3 && !context->getExtensions().sRGB)
4104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004105 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004106 return false;
4107 }
4108 break;
4109
4110 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4111 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4112 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4113 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4114 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4115 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4116 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4117 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4118 if (clientVersion < 3)
4119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004120 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004121 return false;
4122 }
4123 break;
4124
4125 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004126 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004127 return false;
4128 }
4129
4130 // Determine if the attachment is a valid enum
4131 switch (attachment)
4132 {
4133 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004134 case GL_DEPTH:
4135 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004136 if (clientVersion < 3)
4137 {
Geoff Langfa125c92017-10-24 13:01:46 -04004138 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004139 return false;
4140 }
4141 break;
4142
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004143 case GL_DEPTH_STENCIL_ATTACHMENT:
4144 if (clientVersion < 3 && !context->isWebGL1())
4145 {
4146 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4147 return false;
4148 }
4149 break;
4150
Geoff Langfa125c92017-10-24 13:01:46 -04004151 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004152 case GL_DEPTH_ATTACHMENT:
4153 case GL_STENCIL_ATTACHMENT:
4154 break;
4155
4156 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004157 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4158 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4160 {
Geoff Langfa125c92017-10-24 13:01:46 -04004161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004162 return false;
4163 }
4164 break;
4165 }
4166
4167 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4168 ASSERT(framebuffer);
4169
4170 if (framebuffer->id() == 0)
4171 {
4172 if (clientVersion < 3)
4173 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004174 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004175 return false;
4176 }
4177
4178 switch (attachment)
4179 {
4180 case GL_BACK:
4181 case GL_DEPTH:
4182 case GL_STENCIL:
4183 break;
4184
4185 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004187 return false;
4188 }
4189 }
4190 else
4191 {
4192 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4193 {
4194 // Valid attachment query
4195 }
4196 else
4197 {
4198 switch (attachment)
4199 {
4200 case GL_DEPTH_ATTACHMENT:
4201 case GL_STENCIL_ATTACHMENT:
4202 break;
4203
4204 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004205 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004207 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004208 return false;
4209 }
4210 break;
4211
4212 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004213 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004214 return false;
4215 }
4216 }
4217 }
4218
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004219 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004220 if (attachmentObject)
4221 {
4222 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4223 attachmentObject->type() == GL_TEXTURE ||
4224 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4225
4226 switch (pname)
4227 {
4228 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4229 if (attachmentObject->type() != GL_RENDERBUFFER &&
4230 attachmentObject->type() != GL_TEXTURE)
4231 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004233 return false;
4234 }
4235 break;
4236
4237 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4238 if (attachmentObject->type() != GL_TEXTURE)
4239 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004240 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004241 return false;
4242 }
4243 break;
4244
4245 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4246 if (attachmentObject->type() != GL_TEXTURE)
4247 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004248 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004249 return false;
4250 }
4251 break;
4252
4253 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4254 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4255 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004256 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004257 return false;
4258 }
4259 break;
4260
4261 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4262 if (attachmentObject->type() != GL_TEXTURE)
4263 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004264 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004265 return false;
4266 }
4267 break;
4268
4269 default:
4270 break;
4271 }
4272 }
4273 else
4274 {
4275 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4276 // is NONE, then querying any other pname will generate INVALID_ENUM.
4277
4278 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4279 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4280 // INVALID_OPERATION for all other pnames
4281
4282 switch (pname)
4283 {
4284 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4285 break;
4286
4287 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4288 if (clientVersion < 3)
4289 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004290 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004291 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004292 return false;
4293 }
4294 break;
4295
4296 default:
4297 if (clientVersion < 3)
4298 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004299 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004300 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004301 return false;
4302 }
4303 else
4304 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004305 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004306 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004307 return false;
4308 }
4309 }
4310 }
4311
Martin Radeve5285d22017-07-14 16:23:53 +03004312 if (numParams)
4313 {
4314 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4315 {
4316 // Only when the viewport offsets are queried we can have a varying number of output
4317 // parameters.
4318 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4319 *numParams = numViews * 2;
4320 }
4321 else
4322 {
4323 // For all other queries we can have only one output parameter.
4324 *numParams = 1;
4325 }
4326 }
4327
Geoff Langff5b2d52016-09-07 11:32:23 -04004328 return true;
4329}
4330
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004331bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004332 GLenum target,
4333 GLenum attachment,
4334 GLenum pname,
4335 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004336 GLsizei *length,
4337 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004338{
4339 if (!ValidateRobustEntryPoint(context, bufSize))
4340 {
4341 return false;
4342 }
4343
Brandon Jonesd1049182018-03-28 10:02:20 -07004344 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004345 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004346 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004347 {
4348 return false;
4349 }
4350
Brandon Jonesd1049182018-03-28 10:02:20 -07004351 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004352 {
4353 return false;
4354 }
4355
Brandon Jonesd1049182018-03-28 10:02:20 -07004356 SetRobustLengthParam(length, numParams);
4357
Geoff Langff5b2d52016-09-07 11:32:23 -04004358 return true;
4359}
4360
Jamie Madill5b772312018-03-08 20:28:32 -05004361bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004362 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004363 GLenum pname,
4364 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004365 GLsizei *length,
4366 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004367{
4368 if (!ValidateRobustEntryPoint(context, bufSize))
4369 {
4370 return false;
4371 }
4372
Brandon Jonesd1049182018-03-28 10:02:20 -07004373 GLsizei numParams = 0;
4374
4375 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004376 {
4377 return false;
4378 }
4379
Brandon Jonesd1049182018-03-28 10:02:20 -07004380 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004381 {
4382 return false;
4383 }
4384
Brandon Jonesd1049182018-03-28 10:02:20 -07004385 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004386 return true;
4387}
4388
Jamie Madill5b772312018-03-08 20:28:32 -05004389bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004390 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004391 GLenum pname,
4392 GLsizei bufSize,
4393 GLsizei *length,
4394 GLint64 *params)
4395{
Brandon Jonesd1049182018-03-28 10:02:20 -07004396 GLsizei numParams = 0;
4397
Geoff Langebebe1c2016-10-14 12:01:31 -04004398 if (!ValidateRobustEntryPoint(context, bufSize))
4399 {
4400 return false;
4401 }
4402
Brandon Jonesd1049182018-03-28 10:02:20 -07004403 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004404 {
4405 return false;
4406 }
4407
Brandon Jonesd1049182018-03-28 10:02:20 -07004408 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004409 {
4410 return false;
4411 }
4412
Brandon Jonesd1049182018-03-28 10:02:20 -07004413 SetRobustLengthParam(length, numParams);
4414
Geoff Langff5b2d52016-09-07 11:32:23 -04004415 return true;
4416}
4417
Jamie Madill5b772312018-03-08 20:28:32 -05004418bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004419{
4420 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004421 if (numParams)
4422 {
4423 *numParams = 1;
4424 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004425
4426 Program *programObject = GetValidProgram(context, program);
4427 if (!programObject)
4428 {
4429 return false;
4430 }
4431
4432 switch (pname)
4433 {
4434 case GL_DELETE_STATUS:
4435 case GL_LINK_STATUS:
4436 case GL_VALIDATE_STATUS:
4437 case GL_INFO_LOG_LENGTH:
4438 case GL_ATTACHED_SHADERS:
4439 case GL_ACTIVE_ATTRIBUTES:
4440 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4441 case GL_ACTIVE_UNIFORMS:
4442 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4443 break;
4444
4445 case GL_PROGRAM_BINARY_LENGTH:
4446 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004448 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4449 "requires GL_OES_get_program_binary or "
4450 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004451 return false;
4452 }
4453 break;
4454
4455 case GL_ACTIVE_UNIFORM_BLOCKS:
4456 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4457 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4458 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4459 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4460 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4461 if (context->getClientMajorVersion() < 3)
4462 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004463 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004464 return false;
4465 }
4466 break;
4467
Yunchao He61afff12017-03-14 15:34:03 +08004468 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004469 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004470 if (context->getClientVersion() < Version(3, 1))
4471 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004472 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004473 return false;
4474 }
4475 break;
4476
Jiawei Shao6ae51612018-02-23 14:03:25 +08004477 case GL_COMPUTE_WORK_GROUP_SIZE:
4478 if (context->getClientVersion() < Version(3, 1))
4479 {
4480 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4481 return false;
4482 }
4483
4484 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4485 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4486 // program which has not been linked successfully, or which does not contain objects to
4487 // form a compute shader.
4488 if (!programObject->isLinked())
4489 {
4490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4491 return false;
4492 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004493 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004494 {
4495 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4496 return false;
4497 }
4498 break;
4499
Jiawei Shao447bfac2018-03-14 14:23:40 +08004500 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4501 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4502 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4503 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4504 if (!context->getExtensions().geometryShader)
4505 {
4506 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4507 return false;
4508 }
4509
4510 // [EXT_geometry_shader] Chapter 7.12
4511 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4512 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4513 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4514 // successfully, or which does not contain objects to form a geometry shader.
4515 if (!programObject->isLinked())
4516 {
4517 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4518 return false;
4519 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004520 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004521 {
4522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4523 return false;
4524 }
4525 break;
4526
Geoff Langff5b2d52016-09-07 11:32:23 -04004527 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004528 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004529 return false;
4530 }
4531
4532 return true;
4533}
4534
4535bool ValidateGetProgramivRobustANGLE(Context *context,
4536 GLuint program,
4537 GLenum pname,
4538 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004539 GLsizei *length,
4540 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004541{
4542 if (!ValidateRobustEntryPoint(context, bufSize))
4543 {
4544 return false;
4545 }
4546
Brandon Jonesd1049182018-03-28 10:02:20 -07004547 GLsizei numParams = 0;
4548
4549 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004550 {
4551 return false;
4552 }
4553
Brandon Jonesd1049182018-03-28 10:02:20 -07004554 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004555 {
4556 return false;
4557 }
4558
Brandon Jonesd1049182018-03-28 10:02:20 -07004559 SetRobustLengthParam(length, numParams);
4560
Geoff Langff5b2d52016-09-07 11:32:23 -04004561 return true;
4562}
4563
Geoff Lang740d9022016-10-07 11:20:52 -04004564bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4565 GLenum target,
4566 GLenum pname,
4567 GLsizei bufSize,
4568 GLsizei *length,
4569 GLint *params)
4570{
4571 if (!ValidateRobustEntryPoint(context, bufSize))
4572 {
4573 return false;
4574 }
4575
Brandon Jonesd1049182018-03-28 10:02:20 -07004576 GLsizei numParams = 0;
4577
4578 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004579 {
4580 return false;
4581 }
4582
Brandon Jonesd1049182018-03-28 10:02:20 -07004583 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004584 {
4585 return false;
4586 }
4587
Brandon Jonesd1049182018-03-28 10:02:20 -07004588 SetRobustLengthParam(length, numParams);
4589
Geoff Lang740d9022016-10-07 11:20:52 -04004590 return true;
4591}
4592
Geoff Langd7d0ed32016-10-07 11:33:51 -04004593bool ValidateGetShaderivRobustANGLE(Context *context,
4594 GLuint shader,
4595 GLenum pname,
4596 GLsizei bufSize,
4597 GLsizei *length,
4598 GLint *params)
4599{
4600 if (!ValidateRobustEntryPoint(context, bufSize))
4601 {
4602 return false;
4603 }
4604
Brandon Jonesd1049182018-03-28 10:02:20 -07004605 GLsizei numParams = 0;
4606
4607 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004608 {
4609 return false;
4610 }
4611
Brandon Jonesd1049182018-03-28 10:02:20 -07004612 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004613 {
4614 return false;
4615 }
4616
Brandon Jonesd1049182018-03-28 10:02:20 -07004617 SetRobustLengthParam(length, numParams);
4618
Geoff Langd7d0ed32016-10-07 11:33:51 -04004619 return true;
4620}
4621
Geoff Langc1984ed2016-10-07 12:41:00 -04004622bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004623 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004624 GLenum pname,
4625 GLsizei bufSize,
4626 GLsizei *length,
4627 GLfloat *params)
4628{
4629 if (!ValidateRobustEntryPoint(context, bufSize))
4630 {
4631 return false;
4632 }
4633
Brandon Jonesd1049182018-03-28 10:02:20 -07004634 GLsizei numParams = 0;
4635
4636 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004637 {
4638 return false;
4639 }
4640
Brandon Jonesd1049182018-03-28 10:02:20 -07004641 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004642 {
4643 return false;
4644 }
4645
Brandon Jonesd1049182018-03-28 10:02:20 -07004646 SetRobustLengthParam(length, numParams);
4647
Geoff Langc1984ed2016-10-07 12:41:00 -04004648 return true;
4649}
4650
Geoff Langc1984ed2016-10-07 12:41:00 -04004651bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004652 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004653 GLenum pname,
4654 GLsizei bufSize,
4655 GLsizei *length,
4656 GLint *params)
4657{
Brandon Jonesd1049182018-03-28 10:02:20 -07004658
Geoff Langc1984ed2016-10-07 12:41:00 -04004659 if (!ValidateRobustEntryPoint(context, bufSize))
4660 {
4661 return false;
4662 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004663 GLsizei numParams = 0;
4664 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004665 {
4666 return false;
4667 }
4668
Brandon Jonesd1049182018-03-28 10:02:20 -07004669 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004670 {
4671 return false;
4672 }
4673
Brandon Jonesd1049182018-03-28 10:02:20 -07004674 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004675 return true;
4676}
4677
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004678bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4679 TextureType target,
4680 GLenum pname,
4681 GLsizei bufSize,
4682 GLsizei *length,
4683 GLint *params)
4684{
4685 UNIMPLEMENTED();
4686 return false;
4687}
4688
4689bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4690 TextureType target,
4691 GLenum pname,
4692 GLsizei bufSize,
4693 GLsizei *length,
4694 GLuint *params)
4695{
4696 UNIMPLEMENTED();
4697 return false;
4698}
4699
Geoff Langc1984ed2016-10-07 12:41:00 -04004700bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004701 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004702 GLenum pname,
4703 GLsizei bufSize,
4704 const GLfloat *params)
4705{
4706 if (!ValidateRobustEntryPoint(context, bufSize))
4707 {
4708 return false;
4709 }
4710
4711 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4712}
4713
Geoff Langc1984ed2016-10-07 12:41:00 -04004714bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004715 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004716 GLenum pname,
4717 GLsizei bufSize,
4718 const GLint *params)
4719{
4720 if (!ValidateRobustEntryPoint(context, bufSize))
4721 {
4722 return false;
4723 }
4724
4725 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4726}
4727
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004728bool ValidateTexParameterIivRobustANGLE(Context *context,
4729 TextureType target,
4730 GLenum pname,
4731 GLsizei bufSize,
4732 const GLint *params)
4733{
4734 UNIMPLEMENTED();
4735 return false;
4736}
4737
4738bool ValidateTexParameterIuivRobustANGLE(Context *context,
4739 TextureType target,
4740 GLenum pname,
4741 GLsizei bufSize,
4742 const GLuint *params)
4743{
4744 UNIMPLEMENTED();
4745 return false;
4746}
4747
Geoff Langc1984ed2016-10-07 12:41:00 -04004748bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4749 GLuint sampler,
4750 GLenum pname,
4751 GLuint bufSize,
4752 GLsizei *length,
4753 GLfloat *params)
4754{
4755 if (!ValidateRobustEntryPoint(context, bufSize))
4756 {
4757 return false;
4758 }
4759
Brandon Jonesd1049182018-03-28 10:02:20 -07004760 GLsizei numParams = 0;
4761
4762 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004763 {
4764 return false;
4765 }
4766
Brandon Jonesd1049182018-03-28 10:02:20 -07004767 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004768 {
4769 return false;
4770 }
4771
Brandon Jonesd1049182018-03-28 10:02:20 -07004772 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004773 return true;
4774}
4775
Geoff Langc1984ed2016-10-07 12:41:00 -04004776bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4777 GLuint sampler,
4778 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004779 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004780 GLsizei *length,
4781 GLint *params)
4782{
4783 if (!ValidateRobustEntryPoint(context, bufSize))
4784 {
4785 return false;
4786 }
4787
Brandon Jonesd1049182018-03-28 10:02:20 -07004788 GLsizei numParams = 0;
4789
4790 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004791 {
4792 return false;
4793 }
4794
Brandon Jonesd1049182018-03-28 10:02:20 -07004795 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004796 {
4797 return false;
4798 }
4799
Brandon Jonesd1049182018-03-28 10:02:20 -07004800 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004801 return true;
4802}
4803
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004804bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4805 GLuint sampler,
4806 GLenum pname,
4807 GLsizei bufSize,
4808 GLsizei *length,
4809 GLint *params)
4810{
4811 UNIMPLEMENTED();
4812 return false;
4813}
4814
4815bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4816 GLuint sampler,
4817 GLenum pname,
4818 GLsizei bufSize,
4819 GLsizei *length,
4820 GLuint *params)
4821{
4822 UNIMPLEMENTED();
4823 return false;
4824}
4825
Geoff Langc1984ed2016-10-07 12:41:00 -04004826bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4827 GLuint sampler,
4828 GLenum pname,
4829 GLsizei bufSize,
4830 const GLfloat *params)
4831{
4832 if (!ValidateRobustEntryPoint(context, bufSize))
4833 {
4834 return false;
4835 }
4836
4837 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4838}
4839
Geoff Langc1984ed2016-10-07 12:41:00 -04004840bool ValidateSamplerParameterivRobustANGLE(Context *context,
4841 GLuint sampler,
4842 GLenum pname,
4843 GLsizei bufSize,
4844 const GLint *params)
4845{
4846 if (!ValidateRobustEntryPoint(context, bufSize))
4847 {
4848 return false;
4849 }
4850
4851 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4852}
4853
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004854bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4855 GLuint sampler,
4856 GLenum pname,
4857 GLsizei bufSize,
4858 const GLint *param)
4859{
4860 UNIMPLEMENTED();
4861 return false;
4862}
4863
4864bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4865 GLuint sampler,
4866 GLenum pname,
4867 GLsizei bufSize,
4868 const GLuint *param)
4869{
4870 UNIMPLEMENTED();
4871 return false;
4872}
4873
Geoff Lang0b031062016-10-13 14:30:04 -04004874bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4875 GLuint index,
4876 GLenum pname,
4877 GLsizei bufSize,
4878 GLsizei *length,
4879 GLfloat *params)
4880{
4881 if (!ValidateRobustEntryPoint(context, bufSize))
4882 {
4883 return false;
4884 }
4885
Brandon Jonesd1049182018-03-28 10:02:20 -07004886 GLsizei writeLength = 0;
4887
4888 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004889 {
4890 return false;
4891 }
4892
Brandon Jonesd1049182018-03-28 10:02:20 -07004893 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004894 {
4895 return false;
4896 }
4897
Brandon Jonesd1049182018-03-28 10:02:20 -07004898 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004899 return true;
4900}
4901
Geoff Lang0b031062016-10-13 14:30:04 -04004902bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4903 GLuint index,
4904 GLenum pname,
4905 GLsizei bufSize,
4906 GLsizei *length,
4907 GLint *params)
4908{
4909 if (!ValidateRobustEntryPoint(context, bufSize))
4910 {
4911 return false;
4912 }
4913
Brandon Jonesd1049182018-03-28 10:02:20 -07004914 GLsizei writeLength = 0;
4915
4916 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004917 {
4918 return false;
4919 }
4920
Brandon Jonesd1049182018-03-28 10:02:20 -07004921 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004922 {
4923 return false;
4924 }
4925
Brandon Jonesd1049182018-03-28 10:02:20 -07004926 SetRobustLengthParam(length, writeLength);
4927
Geoff Lang0b031062016-10-13 14:30:04 -04004928 return true;
4929}
4930
Geoff Lang0b031062016-10-13 14:30:04 -04004931bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4932 GLuint index,
4933 GLenum pname,
4934 GLsizei bufSize,
4935 GLsizei *length,
4936 void **pointer)
4937{
4938 if (!ValidateRobustEntryPoint(context, bufSize))
4939 {
4940 return false;
4941 }
4942
Brandon Jonesd1049182018-03-28 10:02:20 -07004943 GLsizei writeLength = 0;
4944
4945 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004946 {
4947 return false;
4948 }
4949
Brandon Jonesd1049182018-03-28 10:02:20 -07004950 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004951 {
4952 return false;
4953 }
4954
Brandon Jonesd1049182018-03-28 10:02:20 -07004955 SetRobustLengthParam(length, writeLength);
4956
Geoff Lang0b031062016-10-13 14:30:04 -04004957 return true;
4958}
4959
Geoff Lang0b031062016-10-13 14:30:04 -04004960bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4961 GLuint index,
4962 GLenum pname,
4963 GLsizei bufSize,
4964 GLsizei *length,
4965 GLint *params)
4966{
4967 if (!ValidateRobustEntryPoint(context, bufSize))
4968 {
4969 return false;
4970 }
4971
Brandon Jonesd1049182018-03-28 10:02:20 -07004972 GLsizei writeLength = 0;
4973
4974 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004975 {
4976 return false;
4977 }
4978
Brandon Jonesd1049182018-03-28 10:02:20 -07004979 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004980 {
4981 return false;
4982 }
4983
Brandon Jonesd1049182018-03-28 10:02:20 -07004984 SetRobustLengthParam(length, writeLength);
4985
Geoff Lang0b031062016-10-13 14:30:04 -04004986 return true;
4987}
4988
Geoff Lang0b031062016-10-13 14:30:04 -04004989bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4990 GLuint index,
4991 GLenum pname,
4992 GLsizei bufSize,
4993 GLsizei *length,
4994 GLuint *params)
4995{
4996 if (!ValidateRobustEntryPoint(context, bufSize))
4997 {
4998 return false;
4999 }
5000
Brandon Jonesd1049182018-03-28 10:02:20 -07005001 GLsizei writeLength = 0;
5002
5003 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005004 {
5005 return false;
5006 }
5007
Brandon Jonesd1049182018-03-28 10:02:20 -07005008 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005009 {
5010 return false;
5011 }
5012
Brandon Jonesd1049182018-03-28 10:02:20 -07005013 SetRobustLengthParam(length, writeLength);
5014
Geoff Lang0b031062016-10-13 14:30:04 -04005015 return true;
5016}
5017
Geoff Lang6899b872016-10-14 11:30:13 -04005018bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5019 GLuint program,
5020 GLuint uniformBlockIndex,
5021 GLenum pname,
5022 GLsizei bufSize,
5023 GLsizei *length,
5024 GLint *params)
5025{
5026 if (!ValidateRobustEntryPoint(context, bufSize))
5027 {
5028 return false;
5029 }
5030
Brandon Jonesd1049182018-03-28 10:02:20 -07005031 GLsizei writeLength = 0;
5032
5033 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5034 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005035 {
5036 return false;
5037 }
5038
Brandon Jonesd1049182018-03-28 10:02:20 -07005039 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005040 {
5041 return false;
5042 }
5043
Brandon Jonesd1049182018-03-28 10:02:20 -07005044 SetRobustLengthParam(length, writeLength);
5045
Geoff Lang6899b872016-10-14 11:30:13 -04005046 return true;
5047}
5048
Brandon Jones416aaf92018-04-10 08:10:16 -07005049bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005050 GLenum target,
5051 GLenum internalformat,
5052 GLenum pname,
5053 GLsizei bufSize,
5054 GLsizei *length,
5055 GLint *params)
5056{
5057 if (!ValidateRobustEntryPoint(context, bufSize))
5058 {
5059 return false;
5060 }
5061
Brandon Jonesd1049182018-03-28 10:02:20 -07005062 GLsizei numParams = 0;
5063
5064 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5065 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005066 {
5067 return false;
5068 }
5069
Brandon Jonesd1049182018-03-28 10:02:20 -07005070 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005071 {
5072 return false;
5073 }
5074
Brandon Jonesd1049182018-03-28 10:02:20 -07005075 SetRobustLengthParam(length, numParams);
5076
Geoff Lang0a9661f2016-10-20 10:59:20 -07005077 return true;
5078}
5079
Jamie Madill5b772312018-03-08 20:28:32 -05005080bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005081 GLuint attribIndex,
5082 GLint size,
5083 GLenum type,
5084 GLboolean pureInteger)
5085{
5086 const Caps &caps = context->getCaps();
5087 if (attribIndex >= caps.maxVertexAttributes)
5088 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005089 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005090 return false;
5091 }
5092
5093 if (size < 1 || size > 4)
5094 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005095 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005096 return false;
Shao80957d92017-02-20 21:25:59 +08005097 }
5098
5099 switch (type)
5100 {
5101 case GL_BYTE:
5102 case GL_UNSIGNED_BYTE:
5103 case GL_SHORT:
5104 case GL_UNSIGNED_SHORT:
5105 break;
5106
5107 case GL_INT:
5108 case GL_UNSIGNED_INT:
5109 if (context->getClientMajorVersion() < 3)
5110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005111 context->handleError(InvalidEnum()
5112 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005113 return false;
5114 }
5115 break;
5116
5117 case GL_FIXED:
5118 case GL_FLOAT:
5119 if (pureInteger)
5120 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005122 return false;
5123 }
5124 break;
5125
5126 case GL_HALF_FLOAT:
5127 if (context->getClientMajorVersion() < 3)
5128 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005129 context->handleError(InvalidEnum()
5130 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005131 return false;
5132 }
5133 if (pureInteger)
5134 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005135 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005136 return false;
5137 }
5138 break;
5139
5140 case GL_INT_2_10_10_10_REV:
5141 case GL_UNSIGNED_INT_2_10_10_10_REV:
5142 if (context->getClientMajorVersion() < 3)
5143 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005144 context->handleError(InvalidEnum()
5145 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005146 return false;
5147 }
5148 if (pureInteger)
5149 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005151 return false;
5152 }
5153 if (size != 4)
5154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005155 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5156 "UNSIGNED_INT_2_10_10_10_REV and "
5157 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005158 return false;
5159 }
5160 break;
5161
5162 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005163 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005164 return false;
5165 }
5166
5167 return true;
5168}
5169
Geoff Lang76e65652017-03-27 14:58:02 -04005170// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5171// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5172// specified clear value and the type of a buffer that is being cleared generates an
5173// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005174bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005175 GLint drawbuffer,
5176 const GLenum *validComponentTypes,
5177 size_t validComponentTypeCount)
5178{
5179 const FramebufferAttachment *attachment =
5180 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5181 if (attachment)
5182 {
5183 GLenum componentType = attachment->getFormat().info->componentType;
5184 const GLenum *end = validComponentTypes + validComponentTypeCount;
5185 if (std::find(validComponentTypes, end, componentType) == end)
5186 {
5187 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005188 InvalidOperation()
5189 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005190 return false;
5191 }
5192 }
5193
5194 return true;
5195}
5196
Jamie Madill5b772312018-03-08 20:28:32 -05005197bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005198{
5199 if (!ValidateRobustEntryPoint(context, dataSize))
5200 {
5201 return false;
5202 }
5203
Corentin Wallez336129f2017-10-17 15:55:40 -04005204 gl::Buffer *pixelUnpackBuffer =
5205 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005206 if (pixelUnpackBuffer == nullptr)
5207 {
5208 if (dataSize < imageSize)
5209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005210 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005211 }
5212 }
5213 return true;
5214}
5215
Jamie Madill5b772312018-03-08 20:28:32 -05005216bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005217 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005218 GLenum pname,
5219 bool pointerVersion,
5220 GLsizei *numParams)
5221{
5222 if (numParams)
5223 {
5224 *numParams = 0;
5225 }
5226
Corentin Walleze4477002017-12-01 14:39:58 -05005227 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005228 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005229 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005230 return false;
5231 }
5232
5233 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5234 if (!buffer)
5235 {
5236 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005237 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005238 return false;
5239 }
5240
5241 const Extensions &extensions = context->getExtensions();
5242
5243 switch (pname)
5244 {
5245 case GL_BUFFER_USAGE:
5246 case GL_BUFFER_SIZE:
5247 break;
5248
5249 case GL_BUFFER_ACCESS_OES:
5250 if (!extensions.mapBuffer)
5251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005252 context->handleError(InvalidEnum()
5253 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005254 return false;
5255 }
5256 break;
5257
5258 case GL_BUFFER_MAPPED:
5259 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5260 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5261 !extensions.mapBufferRange)
5262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005263 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5264 "GL_OES_mapbuffer or "
5265 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005266 return false;
5267 }
5268 break;
5269
5270 case GL_BUFFER_MAP_POINTER:
5271 if (!pointerVersion)
5272 {
5273 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005274 InvalidEnum()
5275 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005276 return false;
5277 }
5278 break;
5279
5280 case GL_BUFFER_ACCESS_FLAGS:
5281 case GL_BUFFER_MAP_OFFSET:
5282 case GL_BUFFER_MAP_LENGTH:
5283 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005285 context->handleError(InvalidEnum()
5286 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005287 return false;
5288 }
5289 break;
5290
5291 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005292 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295
5296 // All buffer parameter queries return one value.
5297 if (numParams)
5298 {
5299 *numParams = 1;
5300 }
5301
5302 return true;
5303}
5304
5305bool ValidateGetRenderbufferParameterivBase(Context *context,
5306 GLenum target,
5307 GLenum pname,
5308 GLsizei *length)
5309{
5310 if (length)
5311 {
5312 *length = 0;
5313 }
5314
5315 if (target != GL_RENDERBUFFER)
5316 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005317 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005318 return false;
5319 }
5320
5321 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5322 if (renderbuffer == nullptr)
5323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 return false;
5326 }
5327
5328 switch (pname)
5329 {
5330 case GL_RENDERBUFFER_WIDTH:
5331 case GL_RENDERBUFFER_HEIGHT:
5332 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5333 case GL_RENDERBUFFER_RED_SIZE:
5334 case GL_RENDERBUFFER_GREEN_SIZE:
5335 case GL_RENDERBUFFER_BLUE_SIZE:
5336 case GL_RENDERBUFFER_ALPHA_SIZE:
5337 case GL_RENDERBUFFER_DEPTH_SIZE:
5338 case GL_RENDERBUFFER_STENCIL_SIZE:
5339 break;
5340
5341 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5342 if (!context->getExtensions().framebufferMultisample)
5343 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005344 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005345 return false;
5346 }
5347 break;
5348
5349 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005350 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005351 return false;
5352 }
5353
5354 if (length)
5355 {
5356 *length = 1;
5357 }
5358 return true;
5359}
5360
5361bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5362{
5363 if (length)
5364 {
5365 *length = 0;
5366 }
5367
5368 if (GetValidShader(context, shader) == nullptr)
5369 {
5370 return false;
5371 }
5372
5373 switch (pname)
5374 {
5375 case GL_SHADER_TYPE:
5376 case GL_DELETE_STATUS:
5377 case GL_COMPILE_STATUS:
5378 case GL_INFO_LOG_LENGTH:
5379 case GL_SHADER_SOURCE_LENGTH:
5380 break;
5381
5382 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5383 if (!context->getExtensions().translatedShaderSource)
5384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 return false;
5387 }
5388 break;
5389
5390 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005391 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005392 return false;
5393 }
5394
5395 if (length)
5396 {
5397 *length = 1;
5398 }
5399 return true;
5400}
5401
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005402bool ValidateGetTexParameterBase(Context *context,
5403 TextureType target,
5404 GLenum pname,
5405 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005406{
5407 if (length)
5408 {
5409 *length = 0;
5410 }
5411
5412 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5413 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005414 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005415 return false;
5416 }
5417
5418 if (context->getTargetTexture(target) == nullptr)
5419 {
5420 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005422 return false;
5423 }
5424
5425 switch (pname)
5426 {
5427 case GL_TEXTURE_MAG_FILTER:
5428 case GL_TEXTURE_MIN_FILTER:
5429 case GL_TEXTURE_WRAP_S:
5430 case GL_TEXTURE_WRAP_T:
5431 break;
5432
5433 case GL_TEXTURE_USAGE_ANGLE:
5434 if (!context->getExtensions().textureUsage)
5435 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005436 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005437 return false;
5438 }
5439 break;
5440
5441 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005442 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005443 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005444 return false;
5445 }
5446 break;
5447
5448 case GL_TEXTURE_IMMUTABLE_FORMAT:
5449 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5450 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005451 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005452 return false;
5453 }
5454 break;
5455
5456 case GL_TEXTURE_WRAP_R:
5457 case GL_TEXTURE_IMMUTABLE_LEVELS:
5458 case GL_TEXTURE_SWIZZLE_R:
5459 case GL_TEXTURE_SWIZZLE_G:
5460 case GL_TEXTURE_SWIZZLE_B:
5461 case GL_TEXTURE_SWIZZLE_A:
5462 case GL_TEXTURE_BASE_LEVEL:
5463 case GL_TEXTURE_MAX_LEVEL:
5464 case GL_TEXTURE_MIN_LOD:
5465 case GL_TEXTURE_MAX_LOD:
5466 case GL_TEXTURE_COMPARE_MODE:
5467 case GL_TEXTURE_COMPARE_FUNC:
5468 if (context->getClientMajorVersion() < 3)
5469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005470 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005471 return false;
5472 }
5473 break;
5474
5475 case GL_TEXTURE_SRGB_DECODE_EXT:
5476 if (!context->getExtensions().textureSRGBDecode)
5477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005478 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005479 return false;
5480 }
5481 break;
5482
Yunchao Hebacaa712018-01-30 14:01:39 +08005483 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5484 if (context->getClientVersion() < Version(3, 1))
5485 {
5486 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5487 return false;
5488 }
5489 break;
5490
Jamie Madillbe849e42017-05-02 15:49:00 -04005491 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005492 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005493 return false;
5494 }
5495
5496 if (length)
5497 {
5498 *length = 1;
5499 }
5500 return true;
5501}
5502
5503bool ValidateGetVertexAttribBase(Context *context,
5504 GLuint index,
5505 GLenum pname,
5506 GLsizei *length,
5507 bool pointer,
5508 bool pureIntegerEntryPoint)
5509{
5510 if (length)
5511 {
5512 *length = 0;
5513 }
5514
5515 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005517 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005518 return false;
5519 }
5520
5521 if (index >= context->getCaps().maxVertexAttributes)
5522 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005523 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005524 return false;
5525 }
5526
5527 if (pointer)
5528 {
5529 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5530 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005531 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005532 return false;
5533 }
5534 }
5535 else
5536 {
5537 switch (pname)
5538 {
5539 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5540 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5541 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5542 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5543 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5544 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5545 case GL_CURRENT_VERTEX_ATTRIB:
5546 break;
5547
5548 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5549 static_assert(
5550 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5551 "ANGLE extension enums not equal to GL enums.");
5552 if (context->getClientMajorVersion() < 3 &&
5553 !context->getExtensions().instancedArrays)
5554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005555 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5556 "requires OpenGL ES 3.0 or "
5557 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005558 return false;
5559 }
5560 break;
5561
5562 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5563 if (context->getClientMajorVersion() < 3)
5564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005565 context->handleError(
5566 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 return false;
5568 }
5569 break;
5570
5571 case GL_VERTEX_ATTRIB_BINDING:
5572 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5573 if (context->getClientVersion() < ES_3_1)
5574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005575 context->handleError(InvalidEnum()
5576 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005577 return false;
5578 }
5579 break;
5580
5581 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005582 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005583 return false;
5584 }
5585 }
5586
5587 if (length)
5588 {
5589 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5590 {
5591 *length = 4;
5592 }
5593 else
5594 {
5595 *length = 1;
5596 }
5597 }
5598
5599 return true;
5600}
5601
Jamie Madill4928b7c2017-06-20 12:57:39 -04005602bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005603 GLint x,
5604 GLint y,
5605 GLsizei width,
5606 GLsizei height,
5607 GLenum format,
5608 GLenum type,
5609 GLsizei bufSize,
5610 GLsizei *length,
5611 GLsizei *columns,
5612 GLsizei *rows,
5613 void *pixels)
5614{
5615 if (length != nullptr)
5616 {
5617 *length = 0;
5618 }
5619 if (rows != nullptr)
5620 {
5621 *rows = 0;
5622 }
5623 if (columns != nullptr)
5624 {
5625 *columns = 0;
5626 }
5627
5628 if (width < 0 || height < 0)
5629 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005630 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005631 return false;
5632 }
5633
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005634 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005635
Jamie Madill427064d2018-04-13 16:20:34 -04005636 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005637 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005638 return false;
5639 }
5640
Jamie Madille98b1b52018-03-08 09:47:23 -05005641 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005642 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005643 return false;
5644 }
5645
Jamie Madill690c8eb2018-03-12 15:20:03 -04005646 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005647 ASSERT(framebuffer);
5648
5649 if (framebuffer->getReadBufferState() == GL_NONE)
5650 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005651 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005652 return false;
5653 }
5654
5655 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5656 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5657 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5658 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5659 // situation is an application error that would lead to a crash in ANGLE.
5660 if (readBuffer == nullptr)
5661 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005662 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005663 return false;
5664 }
5665
Martin Radev28031682017-07-28 14:47:56 +03005666 // ANGLE_multiview, Revision 1:
5667 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5668 // current read framebuffer is not NONE.
5669 if (readBuffer->getMultiviewLayout() != GL_NONE)
5670 {
5671 context->handleError(InvalidFramebufferOperation()
5672 << "Attempting to read from a multi-view framebuffer.");
5673 return false;
5674 }
5675
Geoff Lang280ba992017-04-18 16:30:58 -04005676 if (context->getExtensions().webglCompatibility)
5677 {
5678 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5679 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5680 // and type before validating the combination of format and type. However, the
5681 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5682 // verifies that GL_INVALID_OPERATION is generated.
5683 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5684 // dEQP/WebGL.
5685 if (!ValidReadPixelsFormatEnum(context, format))
5686 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005687 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005688 return false;
5689 }
5690
5691 if (!ValidReadPixelsTypeEnum(context, type))
5692 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005693 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005694 return false;
5695 }
5696 }
5697
Jamie Madill690c8eb2018-03-12 15:20:03 -04005698 GLenum currentFormat = GL_NONE;
5699 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5700
5701 GLenum currentType = GL_NONE;
5702 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5703
Jamie Madillbe849e42017-05-02 15:49:00 -04005704 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5705
5706 bool validFormatTypeCombination =
5707 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5708
5709 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5710 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005711 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005712 return false;
5713 }
5714
5715 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005716 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005717 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5718 {
5719 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005720 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005721 return false;
5722 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005723 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5724 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5725 {
5726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5727 return false;
5728 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005729
5730 // .. the data would be packed to the buffer object such that the memory writes required
5731 // would exceed the data store size.
5732 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5733 const gl::Extents size(width, height, 1);
5734 const auto &pack = context->getGLState().getPackState();
5735
5736 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5737 if (endByteOrErr.isError())
5738 {
5739 context->handleError(endByteOrErr.getError());
5740 return false;
5741 }
5742
5743 size_t endByte = endByteOrErr.getResult();
5744 if (bufSize >= 0)
5745 {
5746 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5747 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005748 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005749 return false;
5750 }
5751 }
5752
5753 if (pixelPackBuffer != nullptr)
5754 {
5755 CheckedNumeric<size_t> checkedEndByte(endByte);
5756 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5757 checkedEndByte += checkedOffset;
5758
5759 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5760 {
5761 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005762 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005763 return false;
5764 }
5765 }
5766
5767 if (pixelPackBuffer == nullptr && length != nullptr)
5768 {
5769 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5770 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005771 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005772 return false;
5773 }
5774
5775 *length = static_cast<GLsizei>(endByte);
5776 }
5777
Geoff Langa953b522018-02-21 16:56:23 -05005778 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005779 angle::CheckedNumeric<int> clippedExtent(length);
5780 if (start < 0)
5781 {
5782 // "subtract" the area that is less than 0
5783 clippedExtent += start;
5784 }
5785
Geoff Langa953b522018-02-21 16:56:23 -05005786 angle::CheckedNumeric<int> readExtent = start;
5787 readExtent += length;
5788 if (!readExtent.IsValid())
5789 {
5790 return false;
5791 }
5792
5793 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005794 {
5795 // Subtract the region to the right of the read buffer
5796 clippedExtent -= (readExtent - bufferSize);
5797 }
5798
5799 if (!clippedExtent.IsValid())
5800 {
Geoff Langa953b522018-02-21 16:56:23 -05005801 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005802 }
5803
Geoff Langa953b522018-02-21 16:56:23 -05005804 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5805 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005806 };
5807
Geoff Langa953b522018-02-21 16:56:23 -05005808 GLsizei writtenColumns = 0;
5809 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5810 {
5811 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5812 return false;
5813 }
5814
5815 GLsizei writtenRows = 0;
5816 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5817 {
5818 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5819 return false;
5820 }
5821
Jamie Madillbe849e42017-05-02 15:49:00 -04005822 if (columns != nullptr)
5823 {
Geoff Langa953b522018-02-21 16:56:23 -05005824 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005825 }
5826
5827 if (rows != nullptr)
5828 {
Geoff Langa953b522018-02-21 16:56:23 -05005829 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005830 }
5831
5832 return true;
5833}
5834
5835template <typename ParamType>
5836bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005837 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005838 GLenum pname,
5839 GLsizei bufSize,
5840 const ParamType *params)
5841{
5842 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5843 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005844 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005845 return false;
5846 }
5847
5848 if (context->getTargetTexture(target) == nullptr)
5849 {
5850 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005851 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005852 return false;
5853 }
5854
5855 const GLsizei minBufSize = 1;
5856 if (bufSize >= 0 && bufSize < minBufSize)
5857 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005858 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005859 return false;
5860 }
5861
5862 switch (pname)
5863 {
5864 case GL_TEXTURE_WRAP_R:
5865 case GL_TEXTURE_SWIZZLE_R:
5866 case GL_TEXTURE_SWIZZLE_G:
5867 case GL_TEXTURE_SWIZZLE_B:
5868 case GL_TEXTURE_SWIZZLE_A:
5869 case GL_TEXTURE_BASE_LEVEL:
5870 case GL_TEXTURE_MAX_LEVEL:
5871 case GL_TEXTURE_COMPARE_MODE:
5872 case GL_TEXTURE_COMPARE_FUNC:
5873 case GL_TEXTURE_MIN_LOD:
5874 case GL_TEXTURE_MAX_LOD:
5875 if (context->getClientMajorVersion() < 3)
5876 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005877 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005878 return false;
5879 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005880 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005882 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5883 "available without "
5884 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005885 return false;
5886 }
5887 break;
5888
5889 default:
5890 break;
5891 }
5892
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005893 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005894 {
5895 switch (pname)
5896 {
5897 case GL_TEXTURE_MIN_FILTER:
5898 case GL_TEXTURE_MAG_FILTER:
5899 case GL_TEXTURE_WRAP_S:
5900 case GL_TEXTURE_WRAP_T:
5901 case GL_TEXTURE_WRAP_R:
5902 case GL_TEXTURE_MIN_LOD:
5903 case GL_TEXTURE_MAX_LOD:
5904 case GL_TEXTURE_COMPARE_MODE:
5905 case GL_TEXTURE_COMPARE_FUNC:
5906 context->handleError(InvalidEnum()
5907 << "Invalid parameter for 2D multisampled textures.");
5908 return false;
5909 }
5910 }
5911
Jamie Madillbe849e42017-05-02 15:49:00 -04005912 switch (pname)
5913 {
5914 case GL_TEXTURE_WRAP_S:
5915 case GL_TEXTURE_WRAP_T:
5916 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005917 {
5918 bool restrictedWrapModes =
5919 target == TextureType::External || target == TextureType::Rectangle;
5920 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005921 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005922 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005923 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005924 }
5925 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005926
5927 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005928 {
5929 bool restrictedMinFilter =
5930 target == TextureType::External || target == TextureType::Rectangle;
5931 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005932 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005933 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005934 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005935 }
5936 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005937
5938 case GL_TEXTURE_MAG_FILTER:
5939 if (!ValidateTextureMagFilterValue(context, params))
5940 {
5941 return false;
5942 }
5943 break;
5944
5945 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005946 if (!context->getExtensions().textureUsage)
5947 {
5948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5949 return false;
5950 }
5951
Jamie Madillbe849e42017-05-02 15:49:00 -04005952 switch (ConvertToGLenum(params[0]))
5953 {
5954 case GL_NONE:
5955 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5956 break;
5957
5958 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005959 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005960 return false;
5961 }
5962 break;
5963
5964 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005965 {
5966 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5967 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005968 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005969 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005970 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005971 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5972 }
5973 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005974
5975 case GL_TEXTURE_MIN_LOD:
5976 case GL_TEXTURE_MAX_LOD:
5977 // any value is permissible
5978 break;
5979
5980 case GL_TEXTURE_COMPARE_MODE:
5981 if (!ValidateTextureCompareModeValue(context, params))
5982 {
5983 return false;
5984 }
5985 break;
5986
5987 case GL_TEXTURE_COMPARE_FUNC:
5988 if (!ValidateTextureCompareFuncValue(context, params))
5989 {
5990 return false;
5991 }
5992 break;
5993
5994 case GL_TEXTURE_SWIZZLE_R:
5995 case GL_TEXTURE_SWIZZLE_G:
5996 case GL_TEXTURE_SWIZZLE_B:
5997 case GL_TEXTURE_SWIZZLE_A:
5998 switch (ConvertToGLenum(params[0]))
5999 {
6000 case GL_RED:
6001 case GL_GREEN:
6002 case GL_BLUE:
6003 case GL_ALPHA:
6004 case GL_ZERO:
6005 case GL_ONE:
6006 break;
6007
6008 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006009 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006010 return false;
6011 }
6012 break;
6013
6014 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006015 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006017 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006018 return false;
6019 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006020 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006022 context->handleError(InvalidOperation()
6023 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006024 return false;
6025 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006026 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006027 {
6028 context->handleError(InvalidOperation()
6029 << "Base level must be 0 for multisampled textures.");
6030 return false;
6031 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006032 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006033 {
6034 context->handleError(InvalidOperation()
6035 << "Base level must be 0 for rectangle textures.");
6036 return false;
6037 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006038 break;
6039
6040 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006041 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006043 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006044 return false;
6045 }
6046 break;
6047
6048 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6049 if (context->getClientVersion() < Version(3, 1))
6050 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006052 return false;
6053 }
6054 switch (ConvertToGLenum(params[0]))
6055 {
6056 case GL_DEPTH_COMPONENT:
6057 case GL_STENCIL_INDEX:
6058 break;
6059
6060 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006061 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006062 return false;
6063 }
6064 break;
6065
6066 case GL_TEXTURE_SRGB_DECODE_EXT:
6067 if (!ValidateTextureSRGBDecodeValue(context, params))
6068 {
6069 return false;
6070 }
6071 break;
6072
6073 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006074 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006075 return false;
6076 }
6077
6078 return true;
6079}
6080
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006081template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6082template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006083
Jamie Madill5b772312018-03-08 20:28:32 -05006084bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006085{
6086 if (index >= MAX_VERTEX_ATTRIBS)
6087 {
6088 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6089 return false;
6090 }
6091
6092 return true;
6093}
6094
6095bool ValidateGetActiveUniformBlockivBase(Context *context,
6096 GLuint program,
6097 GLuint uniformBlockIndex,
6098 GLenum pname,
6099 GLsizei *length)
6100{
6101 if (length)
6102 {
6103 *length = 0;
6104 }
6105
6106 if (context->getClientMajorVersion() < 3)
6107 {
6108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6109 return false;
6110 }
6111
6112 Program *programObject = GetValidProgram(context, program);
6113 if (!programObject)
6114 {
6115 return false;
6116 }
6117
6118 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6119 {
6120 context->handleError(InvalidValue()
6121 << "uniformBlockIndex exceeds active uniform block count.");
6122 return false;
6123 }
6124
6125 switch (pname)
6126 {
6127 case GL_UNIFORM_BLOCK_BINDING:
6128 case GL_UNIFORM_BLOCK_DATA_SIZE:
6129 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6130 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6131 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6132 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6133 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6134 break;
6135
6136 default:
6137 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6138 return false;
6139 }
6140
6141 if (length)
6142 {
6143 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6144 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006145 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006146 programObject->getUniformBlockByIndex(uniformBlockIndex);
6147 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6148 }
6149 else
6150 {
6151 *length = 1;
6152 }
6153 }
6154
6155 return true;
6156}
6157
Jamie Madill9696d072017-08-26 23:19:57 -04006158template <typename ParamType>
6159bool ValidateSamplerParameterBase(Context *context,
6160 GLuint sampler,
6161 GLenum pname,
6162 GLsizei bufSize,
6163 ParamType *params)
6164{
6165 if (context->getClientMajorVersion() < 3)
6166 {
6167 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6168 return false;
6169 }
6170
6171 if (!context->isSampler(sampler))
6172 {
6173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6174 return false;
6175 }
6176
6177 const GLsizei minBufSize = 1;
6178 if (bufSize >= 0 && bufSize < minBufSize)
6179 {
6180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6181 return false;
6182 }
6183
6184 switch (pname)
6185 {
6186 case GL_TEXTURE_WRAP_S:
6187 case GL_TEXTURE_WRAP_T:
6188 case GL_TEXTURE_WRAP_R:
6189 if (!ValidateTextureWrapModeValue(context, params, false))
6190 {
6191 return false;
6192 }
6193 break;
6194
6195 case GL_TEXTURE_MIN_FILTER:
6196 if (!ValidateTextureMinFilterValue(context, params, false))
6197 {
6198 return false;
6199 }
6200 break;
6201
6202 case GL_TEXTURE_MAG_FILTER:
6203 if (!ValidateTextureMagFilterValue(context, params))
6204 {
6205 return false;
6206 }
6207 break;
6208
6209 case GL_TEXTURE_MIN_LOD:
6210 case GL_TEXTURE_MAX_LOD:
6211 // any value is permissible
6212 break;
6213
6214 case GL_TEXTURE_COMPARE_MODE:
6215 if (!ValidateTextureCompareModeValue(context, params))
6216 {
6217 return false;
6218 }
6219 break;
6220
6221 case GL_TEXTURE_COMPARE_FUNC:
6222 if (!ValidateTextureCompareFuncValue(context, params))
6223 {
6224 return false;
6225 }
6226 break;
6227
6228 case GL_TEXTURE_SRGB_DECODE_EXT:
6229 if (!ValidateTextureSRGBDecodeValue(context, params))
6230 {
6231 return false;
6232 }
6233 break;
6234
Luc Ferron1b1a8642018-01-23 15:12:01 -05006235 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6236 {
6237 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6238 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6239 {
6240 return false;
6241 }
6242 }
6243 break;
6244
Jamie Madill9696d072017-08-26 23:19:57 -04006245 default:
6246 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6247 return false;
6248 }
6249
6250 return true;
6251}
6252
6253template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6254template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6255
6256bool ValidateGetSamplerParameterBase(Context *context,
6257 GLuint sampler,
6258 GLenum pname,
6259 GLsizei *length)
6260{
6261 if (length)
6262 {
6263 *length = 0;
6264 }
6265
6266 if (context->getClientMajorVersion() < 3)
6267 {
6268 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6269 return false;
6270 }
6271
6272 if (!context->isSampler(sampler))
6273 {
6274 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6275 return false;
6276 }
6277
6278 switch (pname)
6279 {
6280 case GL_TEXTURE_WRAP_S:
6281 case GL_TEXTURE_WRAP_T:
6282 case GL_TEXTURE_WRAP_R:
6283 case GL_TEXTURE_MIN_FILTER:
6284 case GL_TEXTURE_MAG_FILTER:
6285 case GL_TEXTURE_MIN_LOD:
6286 case GL_TEXTURE_MAX_LOD:
6287 case GL_TEXTURE_COMPARE_MODE:
6288 case GL_TEXTURE_COMPARE_FUNC:
6289 break;
6290
Luc Ferron1b1a8642018-01-23 15:12:01 -05006291 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6292 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6293 {
6294 return false;
6295 }
6296 break;
6297
Jamie Madill9696d072017-08-26 23:19:57 -04006298 case GL_TEXTURE_SRGB_DECODE_EXT:
6299 if (!context->getExtensions().textureSRGBDecode)
6300 {
6301 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6302 return false;
6303 }
6304 break;
6305
6306 default:
6307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6308 return false;
6309 }
6310
6311 if (length)
6312 {
6313 *length = 1;
6314 }
6315 return true;
6316}
6317
6318bool ValidateGetInternalFormativBase(Context *context,
6319 GLenum target,
6320 GLenum internalformat,
6321 GLenum pname,
6322 GLsizei bufSize,
6323 GLsizei *numParams)
6324{
6325 if (numParams)
6326 {
6327 *numParams = 0;
6328 }
6329
6330 if (context->getClientMajorVersion() < 3)
6331 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006332 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006333 return false;
6334 }
6335
6336 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6337 if (!formatCaps.renderable)
6338 {
6339 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6340 return false;
6341 }
6342
6343 switch (target)
6344 {
6345 case GL_RENDERBUFFER:
6346 break;
6347
6348 case GL_TEXTURE_2D_MULTISAMPLE:
6349 if (context->getClientVersion() < ES_3_1)
6350 {
6351 context->handleError(InvalidOperation()
6352 << "Texture target requires at least OpenGL ES 3.1.");
6353 return false;
6354 }
6355 break;
6356
6357 default:
6358 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6359 return false;
6360 }
6361
6362 if (bufSize < 0)
6363 {
6364 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6365 return false;
6366 }
6367
6368 GLsizei maxWriteParams = 0;
6369 switch (pname)
6370 {
6371 case GL_NUM_SAMPLE_COUNTS:
6372 maxWriteParams = 1;
6373 break;
6374
6375 case GL_SAMPLES:
6376 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6377 break;
6378
6379 default:
6380 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6381 return false;
6382 }
6383
6384 if (numParams)
6385 {
6386 // glGetInternalFormativ will not overflow bufSize
6387 *numParams = std::min(bufSize, maxWriteParams);
6388 }
6389
6390 return true;
6391}
6392
Jamie Madille98b1b52018-03-08 09:47:23 -05006393bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6394{
Jamie Madill427064d2018-04-13 16:20:34 -04006395 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006396 {
6397 context->handleError(InvalidOperation());
6398 return false;
6399 }
6400 return true;
6401}
6402
Lingfeng Yang038dd532018-03-29 17:31:52 -07006403bool ValidateMultitextureUnit(Context *context, GLenum texture)
6404{
6405 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6406 {
6407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6408 return false;
6409 }
6410 return true;
6411}
6412
Jamie Madillc29968b2016-01-20 11:17:23 -05006413} // namespace gl