blob: 6a5894e18d71682dc6a61e4c8039003447fbc4bc [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
Jamie Madill493f9572018-05-24 19:52:15 -0400497bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
498 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800499{
500 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400501 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800502 {
Jamie Madill493f9572018-05-24 19:52:15 -0400503 case PrimitiveMode::Points:
504 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
505 case PrimitiveMode::Lines:
506 case PrimitiveMode::LineStrip:
507 case PrimitiveMode::LineLoop:
508 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
509 case PrimitiveMode::LinesAdjacency:
510 case PrimitiveMode::LineStripAdjacency:
511 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
512 case PrimitiveMode::Triangles:
513 case PrimitiveMode::TriangleFan:
514 case PrimitiveMode::TriangleStrip:
515 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
516 case PrimitiveMode::TrianglesAdjacency:
517 case PrimitiveMode::TriangleStripAdjacency:
518 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800519 default:
520 UNREACHABLE();
521 return false;
522 }
523}
524
Geoff Langf41a7152016-09-19 15:11:17 -0400525} // anonymous namespace
526
Brandon Jonesd1049182018-03-28 10:02:20 -0700527void SetRobustLengthParam(GLsizei *length, GLsizei value)
528{
529 if (length)
530 {
531 *length = value;
532 }
533}
534
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500535bool IsETC2EACFormat(const GLenum format)
536{
537 // ES 3.1, Table 8.19
538 switch (format)
539 {
540 case GL_COMPRESSED_R11_EAC:
541 case GL_COMPRESSED_SIGNED_R11_EAC:
542 case GL_COMPRESSED_RG11_EAC:
543 case GL_COMPRESSED_SIGNED_RG11_EAC:
544 case GL_COMPRESSED_RGB8_ETC2:
545 case GL_COMPRESSED_SRGB8_ETC2:
546 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
547 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
548 case GL_COMPRESSED_RGBA8_ETC2_EAC:
549 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
550 return true;
551
552 default:
553 return false;
554 }
555}
556
Jamie Madill5b772312018-03-08 20:28:32 -0500557bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400558{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800559 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400560 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800561 case TextureType::_2D:
562 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800563 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400564
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800565 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400566 return context->getExtensions().textureRectangle;
567
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800568 case TextureType::_3D:
569 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800570 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500571
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800572 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800573 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400574
He Yunchaoced53ae2016-11-29 15:00:51 +0800575 default:
576 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500577 }
Jamie Madill35d15012013-10-07 10:46:37 -0400578}
579
Jamie Madill5b772312018-03-08 20:28:32 -0500580bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500581{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800582 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500583 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800584 case TextureType::_2D:
585 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500586 return true;
587
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800588 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400589 return context->getExtensions().textureRectangle;
590
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500591 default:
592 return false;
593 }
594}
595
Jamie Madill5b772312018-03-08 20:28:32 -0500596bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500597{
598 switch (target)
599 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800600 case TextureType::_3D:
601 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300602 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500603
604 default:
605 return false;
606 }
607}
608
Ian Ewellbda75592016-04-18 17:25:54 -0400609// Most texture GL calls are not compatible with external textures, so we have a separate validation
610// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500611bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400612{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800613 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400614 (context->getExtensions().eglImageExternal ||
615 context->getExtensions().eglStreamConsumerExternal);
616}
617
Shannon Woods4dfed832014-03-17 20:03:39 -0400618// This function differs from ValidTextureTarget in that the target must be
619// usable as the destination of a 2D operation-- so a cube face is valid, but
620// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400621// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500622bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400623{
624 switch (target)
625 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800626 case TextureTarget::_2D:
627 case TextureTarget::CubeMapNegativeX:
628 case TextureTarget::CubeMapNegativeY:
629 case TextureTarget::CubeMapNegativeZ:
630 case TextureTarget::CubeMapPositiveX:
631 case TextureTarget::CubeMapPositiveY:
632 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800633 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800634 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400635 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800636 default:
637 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500638 }
639}
640
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800641bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400642 PrimitiveMode transformFeedbackPrimitiveMode,
643 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800644{
645 ASSERT(context);
646
647 if (!context->getExtensions().geometryShader)
648 {
649 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
650 // that does not match the current transform feedback object's draw mode (if transform
651 // feedback is active), (3.0.2, section 2.14, pg 86)
652 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
653 }
654
655 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400656 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800657 {
Jamie Madill493f9572018-05-24 19:52:15 -0400658 case PrimitiveMode::Points:
659 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
660 case PrimitiveMode::Lines:
661 case PrimitiveMode::LineStrip:
662 case PrimitiveMode::LineLoop:
663 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
664 case PrimitiveMode::Triangles:
665 case PrimitiveMode::TriangleFan:
666 case PrimitiveMode::TriangleStrip:
667 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800668 default:
669 UNREACHABLE();
670 return false;
671 }
672}
673
Jamie Madill5b772312018-03-08 20:28:32 -0500674bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400675 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400676 GLsizei count,
677 GLenum type,
678 const GLvoid *indices,
679 GLsizei primcount)
680{
681 if (primcount < 0)
682 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700683 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400684 return false;
685 }
686
687 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
688 {
689 return false;
690 }
691
Jamie Madill9fdaa492018-02-16 10:52:11 -0500692 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400693}
694
695bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400696 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400697 GLint first,
698 GLsizei count,
699 GLsizei primcount)
700{
701 if (primcount < 0)
702 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700703 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400704 return false;
705 }
706
707 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
708 {
709 return false;
710 }
711
Jamie Madill9fdaa492018-02-16 10:52:11 -0500712 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400713}
714
Jamie Madill5b772312018-03-08 20:28:32 -0500715bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400716{
717 // Verify there is at least one active attribute with a divisor of zero
718 const State &state = context->getGLState();
719
720 Program *program = state.getProgram();
721
722 const auto &attribs = state.getVertexArray()->getVertexAttributes();
723 const auto &bindings = state.getVertexArray()->getVertexBindings();
724 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
725 {
726 const VertexAttribute &attrib = attribs[attributeIndex];
727 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300728 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400729 {
730 return true;
731 }
732 }
733
Brandon Jonesafa75152017-07-21 13:11:29 -0700734 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400735 return false;
736}
737
Jamie Madill5b772312018-03-08 20:28:32 -0500738bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500739{
740 switch (target)
741 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800742 case TextureType::_3D:
743 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800744 return true;
745 default:
746 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400747 }
748}
749
Jamie Madill5b772312018-03-08 20:28:32 -0500750bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800751{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800752 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800753 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800754 case TextureType::_2D:
755 case TextureType::_2DArray:
756 case TextureType::_2DMultisample:
757 case TextureType::CubeMap:
758 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800759 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800760 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400761 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800762 default:
763 return false;
764 }
765}
766
Jamie Madill5b772312018-03-08 20:28:32 -0500767bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500768{
He Yunchaoced53ae2016-11-29 15:00:51 +0800769 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
770 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400771 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500772
773 switch (target)
774 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800775 case GL_FRAMEBUFFER:
776 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400777
He Yunchaoced53ae2016-11-29 15:00:51 +0800778 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800779 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400780 return (context->getExtensions().framebufferBlit ||
781 context->getClientMajorVersion() >= 3);
782
He Yunchaoced53ae2016-11-29 15:00:51 +0800783 default:
784 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500785 }
786}
787
Jamie Madill5b772312018-03-08 20:28:32 -0500788bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400789{
Jamie Madillc29968b2016-01-20 11:17:23 -0500790 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400791 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800792 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400793 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800794 case TextureType::_2D:
795 case TextureType::_2DArray:
796 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500797 maxDimension = caps.max2DTextureSize;
798 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800799 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800800 maxDimension = caps.maxCubeMapTextureSize;
801 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800802 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400803 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800804 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800805 maxDimension = caps.max3DTextureSize;
806 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800807 default:
808 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400809 }
810
Brandon Jones6cad5662017-06-14 13:25:13 -0700811 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400812}
813
Jamie Madill5b772312018-03-08 20:28:32 -0500814bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800815 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700816 GLint level,
817 GLsizei width,
818 GLsizei height,
819 GLsizei depth,
820 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400821{
Brandon Jones6cad5662017-06-14 13:25:13 -0700822 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400823 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700824 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400825 return false;
826 }
Austin Kinross08528e12015-10-07 16:24:40 -0700827 // TexSubImage parameters can be NPOT without textureNPOT extension,
828 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500829 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500830 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500831 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400832 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400833 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700834 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400835 return false;
836 }
837
838 if (!ValidMipLevel(context, target, level))
839 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700840 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400841 return false;
842 }
843
844 return true;
845}
846
Geoff Lang966c9402017-04-18 12:38:27 -0400847bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
848{
849 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
850 (size % blockSize == 0);
851}
852
Jamie Madill5b772312018-03-08 20:28:32 -0500853bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500854 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400855 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500856 GLsizei width,
857 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400858{
Geoff Langca271392017-04-05 12:30:00 -0400859 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400860 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400861 {
862 return false;
863 }
864
Geoff Lang966c9402017-04-18 12:38:27 -0400865 if (width < 0 || height < 0)
866 {
867 return false;
868 }
869
870 if (CompressedTextureFormatRequiresExactSize(internalFormat))
871 {
872 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
873 // block size for level 0 but WebGL disallows this.
874 bool smallerThanBlockSizeAllowed =
875 level > 0 || !context->getExtensions().webglCompatibility;
876
877 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
878 smallerThanBlockSizeAllowed) ||
879 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
880 smallerThanBlockSizeAllowed))
881 {
882 return false;
883 }
884 }
885
886 return true;
887}
888
Jamie Madill5b772312018-03-08 20:28:32 -0500889bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400890 GLenum internalFormat,
891 GLint xoffset,
892 GLint yoffset,
893 GLsizei width,
894 GLsizei height,
895 size_t textureWidth,
896 size_t textureHeight)
897{
898 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
899 if (!formatInfo.compressed)
900 {
901 return false;
902 }
903
Geoff Lang44ff5a72017-02-03 15:15:43 -0500904 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400905 {
906 return false;
907 }
908
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500909 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400910 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500911 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400912 yoffset % formatInfo.compressedBlockHeight != 0)
913 {
914 return false;
915 }
916
917 // Allowed to either have data that is a multiple of block size or is smaller than the block
918 // size but fills the entire mip
919 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
920 static_cast<size_t>(width) == textureWidth &&
921 static_cast<size_t>(height) == textureHeight;
922 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
923 (height % formatInfo.compressedBlockHeight) == 0;
924 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400925 {
926 return false;
927 }
928 }
929
Geoff Langd4f180b2013-09-24 13:57:44 -0400930 return true;
931}
932
Jamie Madill5b772312018-03-08 20:28:32 -0500933bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800934 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400935 GLsizei width,
936 GLsizei height,
937 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400938 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400939 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400940 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400941 GLsizei imageSize)
942{
Corentin Wallez336129f2017-10-17 15:55:40 -0400943 gl::Buffer *pixelUnpackBuffer =
944 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400945 if (pixelUnpackBuffer == nullptr && imageSize < 0)
946 {
947 // Checks are not required
948 return true;
949 }
950
951 // ...the data would be unpacked from the buffer object such that the memory reads required
952 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400953 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
954 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400955 const gl::Extents size(width, height, depth);
956 const auto &unpack = context->getGLState().getUnpackState();
957
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800958 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400959 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
960 if (endByteOrErr.isError())
961 {
962 context->handleError(endByteOrErr.getError());
963 return false;
964 }
965
966 GLuint endByte = endByteOrErr.getResult();
967
968 if (pixelUnpackBuffer)
969 {
970 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
971 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
972 checkedEndByte += checkedOffset;
973
974 if (!checkedEndByte.IsValid() ||
975 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
976 {
977 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500978 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400979 return false;
980 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800981 if (context->getExtensions().webglCompatibility &&
982 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
983 {
984 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
985 PixelUnpackBufferBoundForTransformFeedback);
986 return false;
987 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400988 }
989 else
990 {
991 ASSERT(imageSize >= 0);
992 if (pixels == nullptr && imageSize != 0)
993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500994 context->handleError(InvalidOperation()
995 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400996 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400997 }
998
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400999 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001001 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001002 return false;
1003 }
1004 }
1005
1006 return true;
1007}
1008
Corentin Wallezad3ae902018-03-09 13:40:42 -05001009bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -05001010{
Geoff Lang37dde692014-01-31 16:34:54 -05001011 switch (queryType)
1012 {
Corentin Wallezad3ae902018-03-09 13:40:42 -05001013 case QueryType::AnySamples:
1014 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001015 return context->getClientMajorVersion() >= 3 ||
1016 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001017 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +08001018 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -05001019 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +08001020 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001021 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +08001022 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001023 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +08001024 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +08001025 default:
1026 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001027 }
1028}
1029
Jamie Madill5b772312018-03-08 20:28:32 -05001030bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001031 GLenum type,
1032 GLboolean normalized,
1033 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001034 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001035 bool pureInteger)
1036{
1037 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001038 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1039 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1040 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1041 // parameter exceeds 255.
1042 constexpr GLsizei kMaxWebGLStride = 255;
1043 if (stride > kMaxWebGLStride)
1044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001045 context->handleError(InvalidValue()
1046 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001047 return false;
1048 }
1049
1050 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1051 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1052 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1053 // or an INVALID_OPERATION error is generated.
1054 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1055 size_t typeSize = GetVertexFormatTypeSize(internalType);
1056
1057 ASSERT(isPow2(typeSize) && typeSize > 0);
1058 size_t sizeMask = (typeSize - 1);
1059 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1060 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001061 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001062 return false;
1063 }
1064
1065 if ((stride & sizeMask) != 0)
1066 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001067 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001068 return false;
1069 }
1070
1071 return true;
1072}
1073
Jamie Madill5b772312018-03-08 20:28:32 -05001074Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001075{
He Yunchaoced53ae2016-11-29 15:00:51 +08001076 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1077 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1078 // or program object and INVALID_OPERATION if the provided name identifies an object
1079 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001080
Dian Xiang769769a2015-09-09 15:20:08 -07001081 Program *validProgram = context->getProgram(id);
1082
1083 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001084 {
Dian Xiang769769a2015-09-09 15:20:08 -07001085 if (context->getShader(id))
1086 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001087 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001088 }
1089 else
1090 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001091 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001092 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001093 }
Dian Xiang769769a2015-09-09 15:20:08 -07001094
1095 return validProgram;
1096}
1097
Jamie Madill5b772312018-03-08 20:28:32 -05001098Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001099{
1100 // See ValidProgram for spec details.
1101
1102 Shader *validShader = context->getShader(id);
1103
1104 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001105 {
Dian Xiang769769a2015-09-09 15:20:08 -07001106 if (context->getProgram(id))
1107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001109 }
1110 else
1111 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001112 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001113 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001114 }
Dian Xiang769769a2015-09-09 15:20:08 -07001115
1116 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001117}
1118
Geoff Langb1196682014-07-23 13:47:29 -04001119bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001120{
Geoff Langfa125c92017-10-24 13:01:46 -04001121 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001122 {
Geoff Langfa125c92017-10-24 13:01:46 -04001123 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1124 {
1125 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1126 return false;
1127 }
Jamie Madillb4472272014-07-03 10:38:55 -04001128
Geoff Langfa125c92017-10-24 13:01:46 -04001129 // Color attachment 0 is validated below because it is always valid
1130 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001131 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001132 {
Geoff Langfa125c92017-10-24 13:01:46 -04001133 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001134 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001135 }
1136 }
1137 else
1138 {
1139 switch (attachment)
1140 {
Geoff Langfa125c92017-10-24 13:01:46 -04001141 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001142 case GL_DEPTH_ATTACHMENT:
1143 case GL_STENCIL_ATTACHMENT:
1144 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001145
He Yunchaoced53ae2016-11-29 15:00:51 +08001146 case GL_DEPTH_STENCIL_ATTACHMENT:
1147 if (!context->getExtensions().webglCompatibility &&
1148 context->getClientMajorVersion() < 3)
1149 {
Geoff Langfa125c92017-10-24 13:01:46 -04001150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001151 return false;
1152 }
1153 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001154
He Yunchaoced53ae2016-11-29 15:00:51 +08001155 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001156 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001157 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001158 }
1159 }
1160
1161 return true;
1162}
1163
Jamie Madill5b772312018-03-08 20:28:32 -05001164bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001165 GLenum target,
1166 GLsizei samples,
1167 GLenum internalformat,
1168 GLsizei width,
1169 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170{
1171 switch (target)
1172 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001173 case GL_RENDERBUFFER:
1174 break;
1175 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001177 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001178 }
1179
1180 if (width < 0 || height < 0 || samples < 0)
1181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001182 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001183 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001184 }
1185
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001186 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1187 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1188
1189 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001190 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001192 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001193 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001194 }
1195
1196 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1197 // 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 -08001198 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001199 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1200 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001203 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001204 }
1205
Geoff Langaae65a42014-05-26 12:43:44 -04001206 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001208 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001209 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001210 }
1211
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001212 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001213 if (handle == 0)
1214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001216 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001217 }
1218
1219 return true;
1220}
1221
He Yunchaoced53ae2016-11-29 15:00:51 +08001222bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1223 GLenum target,
1224 GLenum attachment,
1225 GLenum renderbuffertarget,
1226 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001227{
Geoff Lange8afa902017-09-27 15:00:43 -04001228 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001230 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001232 }
1233
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001234 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001235
Jamie Madill84115c92015-04-23 15:00:07 -04001236 ASSERT(framebuffer);
1237 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001240 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001241 }
1242
Jamie Madillb4472272014-07-03 10:38:55 -04001243 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001244 {
Jamie Madillb4472272014-07-03 10:38:55 -04001245 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001246 }
1247
Jamie Madillab9d82c2014-01-21 16:38:14 -05001248 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1249 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1250 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1251 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1252 if (renderbuffer != 0)
1253 {
1254 if (!context->getRenderbuffer(renderbuffer))
1255 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001256 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001257 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001258 }
1259 }
1260
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001261 return true;
1262}
1263
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001264bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001265 GLint srcX0,
1266 GLint srcY0,
1267 GLint srcX1,
1268 GLint srcY1,
1269 GLint dstX0,
1270 GLint dstY0,
1271 GLint dstX1,
1272 GLint dstY1,
1273 GLbitfield mask,
1274 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275{
1276 switch (filter)
1277 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001278 case GL_NEAREST:
1279 break;
1280 case GL_LINEAR:
1281 break;
1282 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001283 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001284 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001285 }
1286
1287 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001289 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001290 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 }
1292
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1294 // color buffer, leaving only nearest being unfiltered from above
1295 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001297 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001298 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 }
1300
Jamie Madill51f40ec2016-06-15 14:06:00 -04001301 const auto &glState = context->getGLState();
1302 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1303 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001304
1305 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001307 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001308 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001309 }
1310
Jamie Madill427064d2018-04-13 16:20:34 -04001311 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001312 {
Jamie Madill48faf802014-11-06 15:27:22 -05001313 return false;
1314 }
1315
Jamie Madill427064d2018-04-13 16:20:34 -04001316 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001317 {
Jamie Madill48faf802014-11-06 15:27:22 -05001318 return false;
1319 }
1320
Qin Jiajiaaef92162018-02-27 13:51:44 +08001321 if (readFramebuffer->id() == drawFramebuffer->id())
1322 {
1323 context->handleError(InvalidOperation());
1324 return false;
1325 }
1326
Jamie Madille98b1b52018-03-08 09:47:23 -05001327 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 {
Geoff Langb1196682014-07-23 13:47:29 -04001329 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330 }
1331
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001332 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1333 // always run it in order to avoid triggering driver bugs.
1334 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1335 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001336 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001337 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1338 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001339 }
1340
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1342
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001343 if (mask & GL_COLOR_BUFFER_BIT)
1344 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001345 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001346 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347
He Yunchao66a41a22016-12-15 16:45:05 +08001348 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001349 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001350 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351
Geoff Langa15472a2015-08-11 11:48:03 -04001352 for (size_t drawbufferIdx = 0;
1353 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001354 {
Geoff Langa15472a2015-08-11 11:48:03 -04001355 const FramebufferAttachment *attachment =
1356 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1357 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001359 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360
Geoff Langb2f3d052013-08-13 12:49:27 -04001361 // The GL ES 3.0.2 spec (pg 193) states that:
1362 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001363 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1364 // as well
1365 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1366 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001367 // Changes with EXT_color_buffer_float:
1368 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001369 GLenum readComponentType = readFormat.info->componentType;
1370 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001371 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001372 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001373 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001374 drawComponentType == GL_SIGNED_NORMALIZED);
1375
1376 if (extensions.colorBufferFloat)
1377 {
1378 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1379 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1380
1381 if (readFixedOrFloat != drawFixedOrFloat)
1382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001383 context->handleError(InvalidOperation()
1384 << "If the read buffer contains fixed-point or "
1385 "floating-point values, the draw buffer must "
1386 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001387 return false;
1388 }
1389 }
1390 else if (readFixedPoint != drawFixedPoint)
1391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001392 context->handleError(InvalidOperation()
1393 << "If the read buffer contains fixed-point values, "
1394 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001395 return false;
1396 }
1397
1398 if (readComponentType == GL_UNSIGNED_INT &&
1399 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001401 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001402 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 }
1404
Jamie Madill6163c752015-12-07 16:32:59 -05001405 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001407 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001408 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001409 }
1410
Jamie Madilla3944d42016-07-22 22:13:26 -04001411 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001412 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001414 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001415 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 }
Geoff Lange4915782017-04-12 15:19:07 -04001417
1418 if (context->getExtensions().webglCompatibility &&
1419 *readColorBuffer == *attachment)
1420 {
1421 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001422 InvalidOperation()
1423 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001424 return false;
1425 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 }
1427 }
1428
Jamie Madilla3944d42016-07-22 22:13:26 -04001429 if ((readFormat.info->componentType == GL_INT ||
1430 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1431 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001434 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 }
He Yunchao66a41a22016-12-15 16:45:05 +08001437 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1438 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1439 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1440 // situation is an application error that would lead to a crash in ANGLE.
1441 else if (drawFramebuffer->hasEnabledDrawBuffer())
1442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001443 context->handleError(
1444 InvalidOperation()
1445 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001446 return false;
1447 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 }
1449
He Yunchaoced53ae2016-11-29 15:00:51 +08001450 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001451 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1452 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001453 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001454 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001455 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001456 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001457 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001458 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001459 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001460
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001461 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001462 {
Kenneth Russell69382852017-07-21 16:38:44 -04001463 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001465 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001466 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001467 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001468
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001469 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001470 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001471 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001472 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 }
Geoff Lange4915782017-04-12 15:19:07 -04001474
1475 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001477 context->handleError(
1478 InvalidOperation()
1479 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001480 return false;
1481 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001482 }
He Yunchao66a41a22016-12-15 16:45:05 +08001483 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1484 else if (drawBuffer)
1485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001486 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1487 "depth/stencil attachment of a "
1488 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001489 return false;
1490 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001491 }
1492 }
1493
Martin Radeva3ed4572017-07-27 18:29:37 +03001494 // ANGLE_multiview, Revision 1:
1495 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1496 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1497 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1498 {
1499 context->handleError(InvalidFramebufferOperation()
1500 << "Attempt to read from a multi-view framebuffer.");
1501 return false;
1502 }
1503 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1504 {
1505 context->handleError(InvalidFramebufferOperation()
1506 << "Attempt to write to a multi-view framebuffer.");
1507 return false;
1508 }
1509
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001510 return true;
1511}
1512
Jamie Madill4928b7c2017-06-20 12:57:39 -04001513bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001514 GLint x,
1515 GLint y,
1516 GLsizei width,
1517 GLsizei height,
1518 GLenum format,
1519 GLenum type,
1520 GLsizei bufSize,
1521 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001522 GLsizei *columns,
1523 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001524 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001525{
1526 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001527 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001528 return false;
1529 }
1530
Brandon Jonesd1049182018-03-28 10:02:20 -07001531 GLsizei writeLength = 0;
1532 GLsizei writeColumns = 0;
1533 GLsizei writeRows = 0;
1534
1535 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1536 &writeColumns, &writeRows, pixels))
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 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001542 {
Geoff Langb1196682014-07-23 13:47:29 -04001543 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001544 }
1545
Brandon Jonesd1049182018-03-28 10:02:20 -07001546 SetRobustLengthParam(length, writeLength);
1547 SetRobustLengthParam(columns, writeColumns);
1548 SetRobustLengthParam(rows, writeRows);
1549
Jamie Madillc29968b2016-01-20 11:17:23 -05001550 return true;
1551}
1552
1553bool ValidateReadnPixelsEXT(Context *context,
1554 GLint x,
1555 GLint y,
1556 GLsizei width,
1557 GLsizei height,
1558 GLenum format,
1559 GLenum type,
1560 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001561 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001562{
1563 if (bufSize < 0)
1564 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001565 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001566 return false;
1567 }
1568
Geoff Lang62fce5b2016-09-30 10:46:35 -04001569 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001570 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001571}
Jamie Madill26e91952014-03-05 15:01:27 -05001572
Jamie Madill4928b7c2017-06-20 12:57:39 -04001573bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001574 GLint x,
1575 GLint y,
1576 GLsizei width,
1577 GLsizei height,
1578 GLenum format,
1579 GLenum type,
1580 GLsizei bufSize,
1581 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001582 GLsizei *columns,
1583 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001584 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001585{
Brandon Jonesd1049182018-03-28 10:02:20 -07001586 GLsizei writeLength = 0;
1587 GLsizei writeColumns = 0;
1588 GLsizei writeRows = 0;
1589
Geoff Lang62fce5b2016-09-30 10:46:35 -04001590 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001591 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001592 return false;
1593 }
1594
Brandon Jonesd1049182018-03-28 10:02:20 -07001595 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1596 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001597 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001598 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001599 }
1600
Brandon Jonesd1049182018-03-28 10:02:20 -07001601 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001602 {
1603 return false;
1604 }
1605
Brandon Jonesd1049182018-03-28 10:02:20 -07001606 SetRobustLengthParam(length, writeLength);
1607 SetRobustLengthParam(columns, writeColumns);
1608 SetRobustLengthParam(rows, writeRows);
1609
Geoff Lang62fce5b2016-09-30 10:46:35 -04001610 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001611}
1612
Jamie Madillf0e04492017-08-26 15:28:42 -04001613bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001614{
1615 if (!context->getExtensions().occlusionQueryBoolean &&
1616 !context->getExtensions().disjointTimerQuery)
1617 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001618 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001619 return false;
1620 }
1621
Olli Etuaho41997e72016-03-10 13:38:39 +02001622 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001623}
1624
Jamie Madillf0e04492017-08-26 15:28:42 -04001625bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001626{
1627 if (!context->getExtensions().occlusionQueryBoolean &&
1628 !context->getExtensions().disjointTimerQuery)
1629 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001630 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001631 return false;
1632 }
1633
Olli Etuaho41997e72016-03-10 13:38:39 +02001634 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001635}
1636
Jamie Madillf0e04492017-08-26 15:28:42 -04001637bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1638{
1639 if (!context->getExtensions().occlusionQueryBoolean &&
1640 !context->getExtensions().disjointTimerQuery)
1641 {
1642 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1643 return false;
1644 }
1645
1646 return true;
1647}
1648
Corentin Wallezad3ae902018-03-09 13:40:42 -05001649bool ValidateBeginQueryBase(gl::Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001650{
1651 if (!ValidQueryType(context, target))
1652 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001653 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001654 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001655 }
1656
1657 if (id == 0)
1658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001659 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001660 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001661 }
1662
1663 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1664 // of zero, if the active query object name for <target> is non-zero (for the
1665 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1666 // the active query for either target is non-zero), if <id> is the name of an
1667 // existing query object whose type does not match <target>, or if <id> is the
1668 // active query object name for any query type, the error INVALID_OPERATION is
1669 // generated.
1670
1671 // Ensure no other queries are active
1672 // NOTE: If other queries than occlusion are supported, we will need to check
1673 // separately that:
1674 // a) The query ID passed is not the current active query for any target/type
1675 // b) There are no active queries for the requested target (and in the case
1676 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1677 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001678
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001679 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001681 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001682 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001683 }
1684
1685 Query *queryObject = context->getQuery(id, true, target);
1686
1687 // check that name was obtained with glGenQueries
1688 if (!queryObject)
1689 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001690 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001691 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001692 }
1693
1694 // check for type mismatch
1695 if (queryObject->getType() != target)
1696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001697 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001698 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001699 }
1700
1701 return true;
1702}
1703
Corentin Wallezad3ae902018-03-09 13:40:42 -05001704bool ValidateBeginQueryEXT(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705{
1706 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001707 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001708 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001709 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001710 return false;
1711 }
1712
1713 return ValidateBeginQueryBase(context, target, id);
1714}
1715
Corentin Wallezad3ae902018-03-09 13:40:42 -05001716bool ValidateEndQueryBase(gl::Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001717{
1718 if (!ValidQueryType(context, target))
1719 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001721 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001722 }
1723
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001724 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001725
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001726 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001728 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001729 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001730 }
1731
Jamie Madill45c785d2014-05-13 14:09:34 -04001732 return true;
1733}
1734
Corentin Wallezad3ae902018-03-09 13:40:42 -05001735bool ValidateEndQueryEXT(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736{
1737 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001738 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001739 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001740 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001741 return false;
1742 }
1743
1744 return ValidateEndQueryBase(context, target);
1745}
1746
Corentin Wallezad3ae902018-03-09 13:40:42 -05001747bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748{
1749 if (!context->getExtensions().disjointTimerQuery)
1750 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001751 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752 return false;
1753 }
1754
Corentin Wallezad3ae902018-03-09 13:40:42 -05001755 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001756 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758 return false;
1759 }
1760
1761 Query *queryObject = context->getQuery(id, true, target);
1762 if (queryObject == nullptr)
1763 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001764 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765 return false;
1766 }
1767
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001768 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001771 return false;
1772 }
1773
1774 return true;
1775}
1776
Corentin Wallezad3ae902018-03-09 13:40:42 -05001777bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001778{
Geoff Lang2186c382016-10-14 10:54:54 -04001779 if (numParams)
1780 {
1781 *numParams = 0;
1782 }
1783
Corentin Wallezad3ae902018-03-09 13:40:42 -05001784 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001785 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001786 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001787 return false;
1788 }
1789
1790 switch (pname)
1791 {
1792 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001793 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001795 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001796 return false;
1797 }
1798 break;
1799 case GL_QUERY_COUNTER_BITS_EXT:
1800 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001801 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802 {
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 break;
1807 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001808 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001809 return false;
1810 }
1811
Geoff Lang2186c382016-10-14 10:54:54 -04001812 if (numParams)
1813 {
1814 // All queries return only one value
1815 *numParams = 1;
1816 }
1817
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001818 return true;
1819}
1820
Corentin Wallezad3ae902018-03-09 13:40:42 -05001821bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001822{
1823 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001824 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001825 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001826 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827 return false;
1828 }
1829
Geoff Lang2186c382016-10-14 10:54:54 -04001830 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001831}
1832
Geoff Lang2186c382016-10-14 10:54:54 -04001833bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001834 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001835 GLenum pname,
1836 GLsizei bufSize,
1837 GLsizei *length,
1838 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001839{
Geoff Lang2186c382016-10-14 10:54:54 -04001840 if (!ValidateRobustEntryPoint(context, bufSize))
1841 {
1842 return false;
1843 }
1844
Brandon Jonesd1049182018-03-28 10:02:20 -07001845 GLsizei numParams = 0;
1846
1847 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001848 {
1849 return false;
1850 }
1851
Brandon Jonesd1049182018-03-28 10:02:20 -07001852 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001853 {
1854 return false;
1855 }
1856
Brandon Jonesd1049182018-03-28 10:02:20 -07001857 SetRobustLengthParam(length, numParams);
1858
Geoff Lang2186c382016-10-14 10:54:54 -04001859 return true;
1860}
1861
1862bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1863{
1864 if (numParams)
1865 {
1866 *numParams = 0;
1867 }
1868
Corentin Wallezad3ae902018-03-09 13:40:42 -05001869 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001870
1871 if (!queryObject)
1872 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001874 return false;
1875 }
1876
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001877 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001878 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001880 return false;
1881 }
1882
1883 switch (pname)
1884 {
1885 case GL_QUERY_RESULT_EXT:
1886 case GL_QUERY_RESULT_AVAILABLE_EXT:
1887 break;
1888
1889 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001890 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001891 return false;
1892 }
1893
Geoff Lang2186c382016-10-14 10:54:54 -04001894 if (numParams)
1895 {
1896 *numParams = 1;
1897 }
1898
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001899 return true;
1900}
1901
1902bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1903{
1904 if (!context->getExtensions().disjointTimerQuery)
1905 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001906 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001907 return false;
1908 }
Geoff Lang2186c382016-10-14 10:54:54 -04001909 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1910}
1911
1912bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1913 GLuint id,
1914 GLenum pname,
1915 GLsizei bufSize,
1916 GLsizei *length,
1917 GLint *params)
1918{
1919 if (!context->getExtensions().disjointTimerQuery)
1920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001921 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001922 return false;
1923 }
1924
1925 if (!ValidateRobustEntryPoint(context, bufSize))
1926 {
1927 return false;
1928 }
1929
Brandon Jonesd1049182018-03-28 10:02:20 -07001930 GLsizei numParams = 0;
1931
1932 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001933 {
1934 return false;
1935 }
1936
Brandon Jonesd1049182018-03-28 10:02:20 -07001937 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001938 {
1939 return false;
1940 }
1941
Brandon Jonesd1049182018-03-28 10:02:20 -07001942 SetRobustLengthParam(length, numParams);
1943
Geoff Lang2186c382016-10-14 10:54:54 -04001944 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001945}
1946
1947bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1948{
1949 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001950 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001951 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001952 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001953 return false;
1954 }
Geoff Lang2186c382016-10-14 10:54:54 -04001955 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1956}
1957
1958bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1959 GLuint id,
1960 GLenum pname,
1961 GLsizei bufSize,
1962 GLsizei *length,
1963 GLuint *params)
1964{
1965 if (!context->getExtensions().disjointTimerQuery &&
1966 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001968 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001969 return false;
1970 }
1971
1972 if (!ValidateRobustEntryPoint(context, bufSize))
1973 {
1974 return false;
1975 }
1976
Brandon Jonesd1049182018-03-28 10:02:20 -07001977 GLsizei numParams = 0;
1978
1979 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001980 {
1981 return false;
1982 }
1983
Brandon Jonesd1049182018-03-28 10:02:20 -07001984 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001985 {
1986 return false;
1987 }
1988
Brandon Jonesd1049182018-03-28 10:02:20 -07001989 SetRobustLengthParam(length, numParams);
1990
Geoff Lang2186c382016-10-14 10:54:54 -04001991 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001992}
1993
1994bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1995{
1996 if (!context->getExtensions().disjointTimerQuery)
1997 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001999 return false;
2000 }
Geoff Lang2186c382016-10-14 10:54:54 -04002001 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2002}
2003
2004bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2005 GLuint id,
2006 GLenum pname,
2007 GLsizei bufSize,
2008 GLsizei *length,
2009 GLint64 *params)
2010{
2011 if (!context->getExtensions().disjointTimerQuery)
2012 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002013 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002014 return false;
2015 }
2016
2017 if (!ValidateRobustEntryPoint(context, bufSize))
2018 {
2019 return false;
2020 }
2021
Brandon Jonesd1049182018-03-28 10:02:20 -07002022 GLsizei numParams = 0;
2023
2024 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002025 {
2026 return false;
2027 }
2028
Brandon Jonesd1049182018-03-28 10:02:20 -07002029 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002030 {
2031 return false;
2032 }
2033
Brandon Jonesd1049182018-03-28 10:02:20 -07002034 SetRobustLengthParam(length, numParams);
2035
Geoff Lang2186c382016-10-14 10:54:54 -04002036 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002037}
2038
2039bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2040{
2041 if (!context->getExtensions().disjointTimerQuery)
2042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002043 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002044 return false;
2045 }
Geoff Lang2186c382016-10-14 10:54:54 -04002046 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2047}
2048
2049bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2050 GLuint id,
2051 GLenum pname,
2052 GLsizei bufSize,
2053 GLsizei *length,
2054 GLuint64 *params)
2055{
2056 if (!context->getExtensions().disjointTimerQuery)
2057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002058 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002059 return false;
2060 }
2061
2062 if (!ValidateRobustEntryPoint(context, bufSize))
2063 {
2064 return false;
2065 }
2066
Brandon Jonesd1049182018-03-28 10:02:20 -07002067 GLsizei numParams = 0;
2068
2069 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002070 {
2071 return false;
2072 }
2073
Brandon Jonesd1049182018-03-28 10:02:20 -07002074 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002075 {
2076 return false;
2077 }
2078
Brandon Jonesd1049182018-03-28 10:02:20 -07002079 SetRobustLengthParam(length, numParams);
2080
Geoff Lang2186c382016-10-14 10:54:54 -04002081 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002082}
2083
Jamie Madill5b772312018-03-08 20:28:32 -05002084bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002085 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002086 GLint location,
2087 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002088 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002089{
Jiajia Qin5451d532017-11-16 17:16:34 +08002090 // TODO(Jiajia): Add image uniform check in future.
2091 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002092 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002093 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002094 return false;
2095 }
2096
Jiajia Qin5451d532017-11-16 17:16:34 +08002097 if (!program)
2098 {
2099 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2100 return false;
2101 }
2102
2103 if (!program->isLinked())
2104 {
2105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2106 return false;
2107 }
2108
2109 if (location == -1)
2110 {
2111 // Silently ignore the uniform command
2112 return false;
2113 }
2114
2115 const auto &uniformLocations = program->getUniformLocations();
2116 size_t castedLocation = static_cast<size_t>(location);
2117 if (castedLocation >= uniformLocations.size())
2118 {
2119 context->handleError(InvalidOperation() << "Invalid uniform location");
2120 return false;
2121 }
2122
2123 const auto &uniformLocation = uniformLocations[castedLocation];
2124 if (uniformLocation.ignored)
2125 {
2126 // Silently ignore the uniform command
2127 return false;
2128 }
2129
2130 if (!uniformLocation.used())
2131 {
2132 context->handleError(InvalidOperation());
2133 return false;
2134 }
2135
2136 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2137
2138 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002139 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002140 {
2141 context->handleError(InvalidOperation());
2142 return false;
2143 }
2144
2145 *uniformOut = &uniform;
2146 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002147}
2148
Jamie Madill5b772312018-03-08 20:28:32 -05002149bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002150 GLenum uniformType,
2151 GLsizei count,
2152 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002153{
Jiajia Qin5451d532017-11-16 17:16:34 +08002154 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2155 // It is compatible with INT or BOOL.
2156 // Do these cheap tests first, for a little extra speed.
2157 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002158 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002159 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002160 }
2161
Jiajia Qin5451d532017-11-16 17:16:34 +08002162 if (IsSamplerType(uniformType))
2163 {
2164 // Check that the values are in range.
2165 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2166 for (GLsizei i = 0; i < count; ++i)
2167 {
2168 if (value[i] < 0 || value[i] >= max)
2169 {
2170 context->handleError(InvalidValue() << "sampler uniform value out of range");
2171 return false;
2172 }
2173 }
2174 return true;
2175 }
2176
2177 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2178 return false;
2179}
2180
Jamie Madill5b772312018-03-08 20:28:32 -05002181bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002182{
2183 // Check that the value type is compatible with uniform type.
2184 // Do the cheaper test first, for a little extra speed.
2185 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2186 {
2187 return true;
2188 }
2189
2190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2191 return false;
2192}
2193
Jamie Madill5b772312018-03-08 20:28:32 -05002194bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002195{
2196 // Check that the value type is compatible with uniform type.
2197 if (valueType == uniformType)
2198 {
2199 return true;
2200 }
2201
2202 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2203 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002204}
2205
Jamie Madill5b772312018-03-08 20:28:32 -05002206bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002207{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002208 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002209 gl::Program *programObject = context->getGLState().getProgram();
2210 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2211 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002212}
2213
Jamie Madill5b772312018-03-08 20:28:32 -05002214bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002215{
2216 const LinkedUniform *uniform = nullptr;
2217 gl::Program *programObject = context->getGLState().getProgram();
2218 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2219 ValidateUniform1ivValue(context, uniform->type, count, value);
2220}
2221
Jamie Madill5b772312018-03-08 20:28:32 -05002222bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002223 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002224 GLint location,
2225 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002226 GLboolean transpose)
2227{
Geoff Lang92019432017-11-20 13:09:34 -05002228 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002230 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002231 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002232 }
2233
Jamie Madill62d31cb2015-09-11 13:25:51 -04002234 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002235 gl::Program *programObject = context->getGLState().getProgram();
2236 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2237 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002238}
2239
Jamie Madill5b772312018-03-08 20:28:32 -05002240bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002241{
2242 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002244 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002245 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002246 }
2247
Jamie Madill0af26e12015-03-05 19:54:33 -05002248 const Caps &caps = context->getCaps();
2249
Jamie Madill893ab082014-05-16 16:56:10 -04002250 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2251 {
2252 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2253
Jamie Madill0af26e12015-03-05 19:54:33 -05002254 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002256 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002257 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002258 }
2259 }
2260
2261 switch (pname)
2262 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002263 case GL_TEXTURE_BINDING_2D:
2264 case GL_TEXTURE_BINDING_CUBE_MAP:
2265 case GL_TEXTURE_BINDING_3D:
2266 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002267 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002268 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002269 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2270 if (!context->getExtensions().textureRectangle)
2271 {
2272 context->handleError(InvalidEnum()
2273 << "ANGLE_texture_rectangle extension not present");
2274 return false;
2275 }
2276 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002277 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2278 if (!context->getExtensions().eglStreamConsumerExternal &&
2279 !context->getExtensions().eglImageExternal)
2280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002281 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2282 "nor GL_OES_EGL_image_external "
2283 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002284 return false;
2285 }
2286 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002287
He Yunchaoced53ae2016-11-29 15:00:51 +08002288 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2289 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002290 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002291 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2292 ASSERT(readFramebuffer);
2293
Jamie Madill427064d2018-04-13 16:20:34 -04002294 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002295 {
Geoff Langb1196682014-07-23 13:47:29 -04002296 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002297 }
2298
Jamie Madille98b1b52018-03-08 09:47:23 -05002299 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002300 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002302 return false;
2303 }
2304
Jamie Madille98b1b52018-03-08 09:47:23 -05002305 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002306 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002308 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002309 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002310 }
2311 }
2312 break;
2313
He Yunchaoced53ae2016-11-29 15:00:51 +08002314 default:
2315 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002316 }
2317
2318 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002319 if (*numParams == 0)
2320 {
2321 return false;
2322 }
2323
2324 return true;
2325}
2326
Brandon Jonesd1049182018-03-28 10:02:20 -07002327bool ValidateGetBooleanvRobustANGLE(Context *context,
2328 GLenum pname,
2329 GLsizei bufSize,
2330 GLsizei *length,
2331 GLboolean *params)
2332{
2333 GLenum nativeType;
2334 unsigned int numParams = 0;
2335
2336 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2337 {
2338 return false;
2339 }
2340
2341 SetRobustLengthParam(length, numParams);
2342
2343 return true;
2344}
2345
2346bool ValidateGetFloatvRobustANGLE(Context *context,
2347 GLenum pname,
2348 GLsizei bufSize,
2349 GLsizei *length,
2350 GLfloat *params)
2351{
2352 GLenum nativeType;
2353 unsigned int numParams = 0;
2354
2355 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2356 {
2357 return false;
2358 }
2359
2360 SetRobustLengthParam(length, numParams);
2361
2362 return true;
2363}
2364
2365bool ValidateGetIntegervRobustANGLE(Context *context,
2366 GLenum pname,
2367 GLsizei bufSize,
2368 GLsizei *length,
2369 GLint *data)
2370{
2371 GLenum nativeType;
2372 unsigned int numParams = 0;
2373
2374 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2375 {
2376 return false;
2377 }
2378
2379 SetRobustLengthParam(length, numParams);
2380
2381 return true;
2382}
2383
2384bool ValidateGetInteger64vRobustANGLE(Context *context,
2385 GLenum pname,
2386 GLsizei bufSize,
2387 GLsizei *length,
2388 GLint64 *data)
2389{
2390 GLenum nativeType;
2391 unsigned int numParams = 0;
2392
2393 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2394 {
2395 return false;
2396 }
2397
2398 if (nativeType == GL_INT_64_ANGLEX)
2399 {
2400 CastStateValues(context, nativeType, pname, numParams, data);
2401 return false;
2402 }
2403
2404 SetRobustLengthParam(length, numParams);
2405 return true;
2406}
2407
Jamie Madill5b772312018-03-08 20:28:32 -05002408bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002409 GLenum pname,
2410 GLsizei bufSize,
2411 GLenum *nativeType,
2412 unsigned int *numParams)
2413{
2414 if (!ValidateRobustEntryPoint(context, bufSize))
2415 {
2416 return false;
2417 }
2418
2419 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2420 {
2421 return false;
2422 }
2423
2424 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002425 {
2426 return false;
2427 }
2428
2429 return true;
2430}
2431
Jamie Madill5b772312018-03-08 20:28:32 -05002432bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002433 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002434 GLint level,
2435 GLenum internalformat,
2436 bool isSubImage,
2437 GLint xoffset,
2438 GLint yoffset,
2439 GLint zoffset,
2440 GLint x,
2441 GLint y,
2442 GLsizei width,
2443 GLsizei height,
2444 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002445 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002446{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002447 TextureType texType = TextureTargetToType(target);
2448
Brandon Jones6cad5662017-06-14 13:25:13 -07002449 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002450 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002451 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2452 return false;
2453 }
2454
2455 if (width < 0 || height < 0)
2456 {
2457 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002458 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002459 }
2460
He Yunchaoced53ae2016-11-29 15:00:51 +08002461 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2462 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002464 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002465 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002466 }
2467
2468 if (border != 0)
2469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002470 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002471 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002472 }
2473
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002474 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002475 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002476 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002477 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002478 }
2479
Jamie Madille98b1b52018-03-08 09:47:23 -05002480 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002481 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002482 if (!ValidateFramebufferComplete(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
Jamie Madille98b1b52018-03-08 09:47:23 -05002487 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002488 {
Geoff Langb1196682014-07-23 13:47:29 -04002489 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 }
2491
Martin Radev138064f2016-07-15 12:03:41 +03002492 if (readFramebuffer->getReadBufferState() == GL_NONE)
2493 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002494 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002495 return false;
2496 }
2497
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002498 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2499 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002500 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002501 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002502 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2503 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002504 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002505 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002506 return false;
2507 }
2508
Martin Radev04e2c3b2017-07-27 16:54:35 +03002509 // ANGLE_multiview spec, Revision 1:
2510 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2511 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2512 // is not NONE.
2513 if (source->getMultiviewLayout() != GL_NONE)
2514 {
2515 context->handleError(InvalidFramebufferOperation()
2516 << "The active read framebuffer object has multiview attachments.");
2517 return false;
2518 }
2519
Geoff Langaae65a42014-05-26 12:43:44 -04002520 const gl::Caps &caps = context->getCaps();
2521
Geoff Langaae65a42014-05-26 12:43:44 -04002522 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002523 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002524 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002525 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002526 maxDimension = caps.max2DTextureSize;
2527 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002528
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002529 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002530 maxDimension = caps.maxCubeMapTextureSize;
2531 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002532
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002533 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002534 maxDimension = caps.maxRectangleTextureSize;
2535 break;
2536
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002537 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002538 maxDimension = caps.max2DTextureSize;
2539 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002540
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002541 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002542 maxDimension = caps.max3DTextureSize;
2543 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002544
He Yunchaoced53ae2016-11-29 15:00:51 +08002545 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002546 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002547 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002548 }
2549
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002550 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002551 if (!texture)
2552 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002553 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002554 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002555 }
2556
Geoff Lang69cce582015-09-17 13:20:36 -04002557 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002559 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002560 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002561 }
2562
Geoff Langca271392017-04-05 12:30:00 -04002563 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002564 isSubImage ? *texture->getFormat(target, level).info
2565 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002566
Geoff Lang966c9402017-04-18 12:38:27 -04002567 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002569 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002570 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002571 }
2572
2573 if (isSubImage)
2574 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002575 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2576 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2577 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002579 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002580 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002581 }
2582 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002583 else
2584 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002585 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002586 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002587 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002588 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002589 }
2590
Geoff Langeb66a6e2016-10-31 13:06:12 -04002591 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002592 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002593 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002594 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002595 }
2596
2597 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002598 if (static_cast<int>(width) > maxLevelDimension ||
2599 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002600 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002601 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002602 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002603 }
2604 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002605
Jamie Madill0c8abca2016-07-22 20:21:26 -04002606 if (textureFormatOut)
2607 {
2608 *textureFormatOut = texture->getFormat(target, level);
2609 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002610
2611 // Detect texture copying feedback loops for WebGL.
2612 if (context->getExtensions().webglCompatibility)
2613 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002614 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002615 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002616 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002617 return false;
2618 }
2619 }
2620
Jamie Madill560a8d82014-05-21 13:06:20 -04002621 return true;
2622}
2623
Jamie Madill493f9572018-05-24 19:52:15 -04002624bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002625{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002626 const Extensions &extensions = context->getExtensions();
2627
Jamie Madill1aeb1312014-06-20 13:21:25 -04002628 switch (mode)
2629 {
Jamie Madill493f9572018-05-24 19:52:15 -04002630 case PrimitiveMode::Points:
2631 case PrimitiveMode::Lines:
2632 case PrimitiveMode::LineLoop:
2633 case PrimitiveMode::LineStrip:
2634 case PrimitiveMode::Triangles:
2635 case PrimitiveMode::TriangleStrip:
2636 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002637 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002638
Jamie Madill493f9572018-05-24 19:52:15 -04002639 case PrimitiveMode::LinesAdjacency:
2640 case PrimitiveMode::LineStripAdjacency:
2641 case PrimitiveMode::TrianglesAdjacency:
2642 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002643 if (!extensions.geometryShader)
2644 {
2645 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2646 return false;
2647 }
2648 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002649 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002650 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002651 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002652 }
2653
Jamie Madill250d33f2014-06-06 17:09:03 -04002654 if (count < 0)
2655 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002656 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002657 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002658 }
2659
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002660 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002661
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002662 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2663 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2664 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2665 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002666 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002667 // Check for mapped buffers
2668 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002669 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002670 {
2671 context->handleError(InvalidOperation());
2672 return false;
2673 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002674 }
2675
Jamie Madillcbcde722017-01-06 14:50:00 -05002676 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2677 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002678 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002679 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002680 {
Ken Russellb9f92502018-01-27 19:00:26 -08002681 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002682 const FramebufferAttachment *dsAttachment =
2683 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002684 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2685 ASSERT(stencilBits <= 8);
2686
Jinyoung Hur85769f02015-10-20 17:08:44 -04002687 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002688 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002689 {
Ken Russellb9f92502018-01-27 19:00:26 -08002690 GLuint maxStencilValue = (1 << stencilBits) - 1;
2691
2692 bool differentRefs =
2693 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2694 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2695 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2696 (depthStencilState.stencilBackWritemask & maxStencilValue);
2697 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2698 (depthStencilState.stencilBackMask & maxStencilValue);
2699
2700 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002701 {
Ken Russellb9f92502018-01-27 19:00:26 -08002702 if (!extensions.webglCompatibility)
2703 {
2704 ERR() << "This ANGLE implementation does not support separate front/back "
2705 "stencil writemasks, reference values, or stencil mask values.";
2706 }
2707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2708 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002709 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002710 }
Jamie Madillac528012014-06-20 13:21:23 -04002711 }
2712
Jamie Madill427064d2018-04-13 16:20:34 -04002713 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002714 {
Geoff Langb1196682014-07-23 13:47:29 -04002715 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002716 }
2717
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002718 // If we are running GLES1, there is no current program.
2719 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002720 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002721
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002722 gl::Program *program = state.getProgram();
2723 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002724 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002725 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002726 return false;
2727 }
Martin Radev7e69f762017-07-27 14:54:13 +03002728
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002729 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2730 // vertex shader stage or fragment shader stage is a undefined behaviour.
2731 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2732 // produce undefined result.
2733 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2734 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002735 {
2736 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002737 << "It is a undefined behaviour to render without "
2738 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002739 return false;
2740 }
Martin Radevffe754b2017-07-31 10:38:07 +03002741
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002742 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002743 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002744 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002745 return false;
2746 }
2747
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002748 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002749 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002750 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2751 const int framebufferNumViews = framebuffer->getNumViews();
2752 if (framebufferNumViews != programNumViews)
2753 {
2754 context->handleError(InvalidOperation()
2755 << "The number of views in the active program "
2756 "and draw framebuffer does not match.");
2757 return false;
2758 }
2759
2760 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2761 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2762 framebufferNumViews > 1)
2763 {
2764 context->handleError(InvalidOperation()
2765 << "There is an active transform feedback object "
2766 "when the number of views in the active draw "
2767 "framebuffer is greater than 1.");
2768 return false;
2769 }
2770
2771 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2772 state.isQueryActive(QueryType::TimeElapsed))
2773 {
2774 context->handleError(InvalidOperation()
2775 << "There is an active query for target "
2776 "GL_TIME_ELAPSED_EXT when the number of "
2777 "views in the active draw framebuffer is "
2778 "greater than 1.");
2779 return false;
2780 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002781 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002782
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002783 // Do geometry shader specific validations
2784 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002785 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002786 if (!IsCompatibleDrawModeWithGeometryShader(
2787 mode, program->getGeometryShaderInputPrimitiveType()))
2788 {
2789 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2790 IncompatibleDrawModeAgainstGeometryShader);
2791 return false;
2792 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002793 }
Geoff Lange0cff192017-05-30 13:04:56 -04002794
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002795 // Uniform buffer validation
2796 for (unsigned int uniformBlockIndex = 0;
2797 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002798 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002799 const gl::InterfaceBlock &uniformBlock =
2800 program->getUniformBlockByIndex(uniformBlockIndex);
2801 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2802 const OffsetBindingPointer<Buffer> &uniformBuffer =
2803 state.getIndexedUniformBuffer(blockBinding);
2804
2805 if (uniformBuffer.get() == nullptr)
2806 {
2807 // undefined behaviour
2808 context->handleError(
2809 InvalidOperation()
2810 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2811 return false;
2812 }
2813
2814 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2815 if (uniformBufferSize < uniformBlock.dataSize)
2816 {
2817 // undefined behaviour
2818 context->handleError(
2819 InvalidOperation()
2820 << "It is undefined behaviour to use a uniform buffer that is too small.");
2821 return false;
2822 }
2823
2824 if (extensions.webglCompatibility &&
2825 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2826 {
2827 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2828 UniformBufferBoundForTransformFeedback);
2829 return false;
2830 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002831 }
2832
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002833 // Do some additonal WebGL-specific validation
2834 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002835 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002836 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2837 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2838 transformFeedbackObject->buffersBoundForOtherUse())
2839 {
2840 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2841 TransformFeedbackBufferDoubleBound);
2842 return false;
2843 }
2844 // Detect rendering feedback loops for WebGL.
2845 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2846 {
2847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2848 return false;
2849 }
2850
2851 // Detect that the vertex shader input types match the attribute types
2852 if (!ValidateVertexShaderAttributeTypeMatch(context))
2853 {
2854 return false;
2855 }
2856
2857 // Detect that the color buffer types match the fragment shader output types
2858 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2859 {
2860 return false;
2861 }
Geoff Lange0cff192017-05-30 13:04:56 -04002862 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002863 }
2864
Jamie Madill9fdaa492018-02-16 10:52:11 -05002865 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002866}
2867
Jamie Madill5b772312018-03-08 20:28:32 -05002868bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002869 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002870 GLint first,
2871 GLsizei count,
2872 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002873{
Jamie Madillfd716582014-06-06 17:09:04 -04002874 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002875 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002876 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002877 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002878 }
2879
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002880 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002881 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002882 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002883 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002884 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002885 if (!ValidateTransformFeedbackPrimitiveMode(context,
2886 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002887 {
James Darpinian30b604d2018-03-12 17:26:57 -07002888 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2889 return false;
2890 }
2891
2892 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2893 {
2894 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2895 return false;
2896 }
Jamie Madillfd716582014-06-06 17:09:04 -04002897 }
2898
Jiajia Qind9671222016-11-29 16:30:31 +08002899 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002900 {
2901 return false;
2902 }
2903
Corentin Wallez71168a02016-12-19 15:11:18 -08002904 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002905 // - first < 0 has been checked as an error condition.
2906 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002907 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002908 ASSERT(first >= 0);
2909 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002910 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002911 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2912 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2913 {
2914 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2915 return false;
2916 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002917
Jamie Madill9fdaa492018-02-16 10:52:11 -05002918 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2919 {
2920 return false;
2921 }
Jamie Madillfd716582014-06-06 17:09:04 -04002922 }
2923
2924 return true;
2925}
2926
He Yunchaoced53ae2016-11-29 15:00:51 +08002927bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002928 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002929 GLint first,
2930 GLsizei count,
2931 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002932{
Geoff Lang63c5a592017-09-27 14:08:16 -04002933 if (!context->getExtensions().instancedArrays)
2934 {
2935 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2936 return false;
2937 }
2938
Corentin Wallez170efbf2017-05-02 13:45:01 -04002939 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002940 {
2941 return false;
2942 }
2943
Corentin Wallez0dc97812017-06-22 14:38:44 -04002944 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002945}
2946
Jamie Madill493f9572018-05-24 19:52:15 -04002947bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002948{
Jamie Madill250d33f2014-06-06 17:09:03 -04002949 switch (type)
2950 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002951 case GL_UNSIGNED_BYTE:
2952 case GL_UNSIGNED_SHORT:
2953 break;
2954 case GL_UNSIGNED_INT:
2955 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002958 return false;
2959 }
2960 break;
2961 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002962 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002963 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002964 }
2965
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002966 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002967
2968 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002969 if (curTransformFeedback && curTransformFeedback->isActive() &&
2970 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002971 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002972 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2973 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2974 if (context->getExtensions().geometryShader)
2975 {
2976 if (!ValidateTransformFeedbackPrimitiveMode(
2977 context, curTransformFeedback->getPrimitiveMode(), mode))
2978 {
2979 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2980 return false;
2981 }
2982 }
2983 else
2984 {
2985 // It is an invalid operation to call DrawElements, DrawRangeElements or
2986 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2987 // 86)
2988 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2989 UnsupportedDrawModeForTransformFeedback);
2990 return false;
2991 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002992 }
2993
Jiajia Qind9671222016-11-29 16:30:31 +08002994 return true;
2995}
2996
Jamie Madill5b772312018-03-08 20:28:32 -05002997bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002998 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002999 GLsizei count,
3000 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003001 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003002 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003003{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003004 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003005 return false;
3006
3007 const State &state = context->getGLState();
3008
Corentin Wallez170efbf2017-05-02 13:45:01 -04003009 if (!ValidateDrawBase(context, mode, count))
3010 {
3011 return false;
3012 }
3013
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003014 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
3015 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3016 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3017 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04003018 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003019 // Check for mapped buffers
3020 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04003021 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003022 {
3023 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3024 return false;
3025 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003026 }
3027
He Yunchaoced53ae2016-11-29 15:00:51 +08003028 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003029 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003030
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003031 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3032
3033 if (context->getExtensions().webglCompatibility)
3034 {
3035 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3036 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3037 {
3038 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3039 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3040 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003041 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003042 return false;
3043 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003044
3045 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3046 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3047 // error is generated.
3048 if (reinterpret_cast<intptr_t>(indices) < 0)
3049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003050 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003051 return false;
3052 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003053 }
3054
3055 if (context->getExtensions().webglCompatibility ||
3056 !context->getGLState().areClientArraysEnabled())
3057 {
Brandon Jones2a018152018-06-08 15:59:26 -07003058 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003059 {
3060 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003061 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3062 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003063 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003064 return false;
3065 }
3066 }
3067
Jamie Madill9fdaa492018-02-16 10:52:11 -05003068 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003069 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003070 // This is an application error that would normally result in a crash, but we catch it and
3071 // return an error
3072 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3073 return false;
3074 }
3075
3076 if (count > 0 && elementArrayBuffer)
3077 {
3078 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3079 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3080 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3081 constexpr uint64_t kMaxTypeSize = 8;
3082 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3083 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3084 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3085
3086 uint64_t typeSize = typeBytes;
3087 uint64_t elementCount = static_cast<uint64_t>(count);
3088 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3089
3090 // Doing the multiplication here is overflow-safe
3091 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3092
3093 // The offset can be any value, check for overflows
3094 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3095 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003096 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3098 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003099 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003100
3101 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3102 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003103 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3105 return false;
3106 }
3107
3108 ASSERT(isPow2(typeSize) && typeSize > 0);
3109 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3110 {
3111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003112 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003113 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003114
3115 if (context->getExtensions().webglCompatibility &&
3116 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3117 {
3118 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3119 ElementArrayBufferBoundForTransformFeedback);
3120 return false;
3121 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003122 }
3123
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003124 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003125 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003126 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3127 // access is enabled.
3128 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3129 {
3130 return false;
3131 }
3132 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003133 else if (count == 0)
3134 {
3135 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3136 // count.
3137 if (!ValidateDrawAttribs(context, 0, 0, 0))
3138 {
3139 return false;
3140 }
3141 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003142 else
3143 {
3144 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003145 const DrawCallParams &params = context->getParams<DrawCallParams>();
3146 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3147 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003148
3149 // If we use an index greater than our maximum supported index range, return an error.
3150 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3151 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003152 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003153 {
3154 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3155 return false;
3156 }
3157
Jamie Madill6f5444d2018-03-14 10:08:11 -04003158 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3159 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003160 {
3161 return false;
3162 }
3163
3164 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003165 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003166 }
3167
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003168 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003169}
3170
Jamie Madill5b772312018-03-08 20:28:32 -05003171bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003172 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003173 GLsizei count,
3174 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003175 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003176 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003177{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003178 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003179}
3180
Geoff Lang3edfe032015-09-04 16:38:24 -04003181bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003182 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003183 GLsizei count,
3184 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003185 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003186 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003187{
Geoff Lang63c5a592017-09-27 14:08:16 -04003188 if (!context->getExtensions().instancedArrays)
3189 {
3190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3191 return false;
3192 }
3193
Corentin Wallez170efbf2017-05-02 13:45:01 -04003194 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003195 {
3196 return false;
3197 }
3198
Corentin Wallez0dc97812017-06-22 14:38:44 -04003199 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003200}
3201
He Yunchaoced53ae2016-11-29 15:00:51 +08003202bool ValidateFramebufferTextureBase(Context *context,
3203 GLenum target,
3204 GLenum attachment,
3205 GLuint texture,
3206 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003207{
Geoff Lange8afa902017-09-27 15:00:43 -04003208 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003209 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003210 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003211 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003212 }
3213
3214 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003215 {
3216 return false;
3217 }
3218
Jamie Madill55ec3b12014-07-03 10:38:57 -04003219 if (texture != 0)
3220 {
3221 gl::Texture *tex = context->getTexture(texture);
3222
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003223 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003225 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003226 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003227 }
3228
3229 if (level < 0)
3230 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003231 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003232 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003233 }
3234 }
3235
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003236 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003237 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003238
Jamie Madill84115c92015-04-23 15:00:07 -04003239 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003240 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003241 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003242 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003243 }
3244
3245 return true;
3246}
3247
Geoff Langb1196682014-07-23 13:47:29 -04003248bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003249{
3250 if (program == 0)
3251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003252 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003253 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003254 }
3255
Dian Xiang769769a2015-09-09 15:20:08 -07003256 gl::Program *programObject = GetValidProgram(context, program);
3257 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003258 {
3259 return false;
3260 }
3261
Jamie Madill0063c512014-08-25 15:47:53 -04003262 if (!programObject || !programObject->isLinked())
3263 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003264 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003265 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003266 }
3267
Geoff Lang7dd2e102014-11-10 15:19:26 -05003268 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003270 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003271 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003272 }
3273
Jamie Madill0063c512014-08-25 15:47:53 -04003274 return true;
3275}
3276
Geoff Langf41d0ee2016-10-07 13:04:23 -04003277static bool ValidateSizedGetUniform(Context *context,
3278 GLuint program,
3279 GLint location,
3280 GLsizei bufSize,
3281 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003282{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003283 if (length)
3284 {
3285 *length = 0;
3286 }
3287
Jamie Madill78f41802014-08-25 15:47:55 -04003288 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003289 {
Jamie Madill78f41802014-08-25 15:47:55 -04003290 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003291 }
3292
Geoff Langf41d0ee2016-10-07 13:04:23 -04003293 if (bufSize < 0)
3294 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003295 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003296 return false;
3297 }
3298
Jamie Madilla502c742014-08-28 17:19:13 -04003299 gl::Program *programObject = context->getProgram(program);
3300 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003301
Jamie Madill78f41802014-08-25 15:47:55 -04003302 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003303 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003304 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003305 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003306 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003307 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003308 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003309 }
3310
Geoff Langf41d0ee2016-10-07 13:04:23 -04003311 if (length)
3312 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003313 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003314 }
3315
Jamie Madill0063c512014-08-25 15:47:53 -04003316 return true;
3317}
3318
He Yunchaoced53ae2016-11-29 15:00:51 +08003319bool ValidateGetnUniformfvEXT(Context *context,
3320 GLuint program,
3321 GLint location,
3322 GLsizei bufSize,
3323 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003324{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003325 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003326}
3327
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003328bool ValidateGetnUniformfvRobustANGLE(Context *context,
3329 GLuint program,
3330 GLint location,
3331 GLsizei bufSize,
3332 GLsizei *length,
3333 GLfloat *params)
3334{
3335 UNIMPLEMENTED();
3336 return false;
3337}
3338
He Yunchaoced53ae2016-11-29 15:00:51 +08003339bool ValidateGetnUniformivEXT(Context *context,
3340 GLuint program,
3341 GLint location,
3342 GLsizei bufSize,
3343 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003344{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003345 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3346}
3347
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003348bool ValidateGetnUniformivRobustANGLE(Context *context,
3349 GLuint program,
3350 GLint location,
3351 GLsizei bufSize,
3352 GLsizei *length,
3353 GLint *params)
3354{
3355 UNIMPLEMENTED();
3356 return false;
3357}
3358
3359bool ValidateGetnUniformuivRobustANGLE(Context *context,
3360 GLuint program,
3361 GLint location,
3362 GLsizei bufSize,
3363 GLsizei *length,
3364 GLuint *params)
3365{
3366 UNIMPLEMENTED();
3367 return false;
3368}
3369
Geoff Langf41d0ee2016-10-07 13:04:23 -04003370bool ValidateGetUniformfvRobustANGLE(Context *context,
3371 GLuint program,
3372 GLint location,
3373 GLsizei bufSize,
3374 GLsizei *length,
3375 GLfloat *params)
3376{
3377 if (!ValidateRobustEntryPoint(context, bufSize))
3378 {
3379 return false;
3380 }
3381
Brandon Jonesd1049182018-03-28 10:02:20 -07003382 GLsizei writeLength = 0;
3383
Geoff Langf41d0ee2016-10-07 13:04:23 -04003384 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003385 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3386 {
3387 return false;
3388 }
3389
3390 SetRobustLengthParam(length, writeLength);
3391
3392 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003393}
3394
3395bool ValidateGetUniformivRobustANGLE(Context *context,
3396 GLuint program,
3397 GLint location,
3398 GLsizei bufSize,
3399 GLsizei *length,
3400 GLint *params)
3401{
3402 if (!ValidateRobustEntryPoint(context, bufSize))
3403 {
3404 return false;
3405 }
3406
Brandon Jonesd1049182018-03-28 10:02:20 -07003407 GLsizei writeLength = 0;
3408
Geoff Langf41d0ee2016-10-07 13:04:23 -04003409 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003410 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3411 {
3412 return false;
3413 }
3414
3415 SetRobustLengthParam(length, writeLength);
3416
3417 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003418}
3419
3420bool ValidateGetUniformuivRobustANGLE(Context *context,
3421 GLuint program,
3422 GLint location,
3423 GLsizei bufSize,
3424 GLsizei *length,
3425 GLuint *params)
3426{
3427 if (!ValidateRobustEntryPoint(context, bufSize))
3428 {
3429 return false;
3430 }
3431
3432 if (context->getClientMajorVersion() < 3)
3433 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003435 return false;
3436 }
3437
Brandon Jonesd1049182018-03-28 10:02:20 -07003438 GLsizei writeLength = 0;
3439
Geoff Langf41d0ee2016-10-07 13:04:23 -04003440 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003441 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3442 {
3443 return false;
3444 }
3445
3446 SetRobustLengthParam(length, writeLength);
3447
3448 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003449}
3450
He Yunchaoced53ae2016-11-29 15:00:51 +08003451bool ValidateDiscardFramebufferBase(Context *context,
3452 GLenum target,
3453 GLsizei numAttachments,
3454 const GLenum *attachments,
3455 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003456{
3457 if (numAttachments < 0)
3458 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003459 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003460 return false;
3461 }
3462
3463 for (GLsizei i = 0; i < numAttachments; ++i)
3464 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003465 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003466 {
3467 if (defaultFramebuffer)
3468 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003470 return false;
3471 }
3472
3473 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003475 context->handleError(InvalidOperation() << "Requested color attachment is "
3476 "greater than the maximum supported "
3477 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003478 return false;
3479 }
3480 }
3481 else
3482 {
3483 switch (attachments[i])
3484 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003485 case GL_DEPTH_ATTACHMENT:
3486 case GL_STENCIL_ATTACHMENT:
3487 case GL_DEPTH_STENCIL_ATTACHMENT:
3488 if (defaultFramebuffer)
3489 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003490 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3491 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003492 return false;
3493 }
3494 break;
3495 case GL_COLOR:
3496 case GL_DEPTH:
3497 case GL_STENCIL:
3498 if (!defaultFramebuffer)
3499 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003500 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3501 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003502 return false;
3503 }
3504 break;
3505 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003506 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003507 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003508 }
3509 }
3510 }
3511
3512 return true;
3513}
3514
Austin Kinross6ee1e782015-05-29 17:05:37 -07003515bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3516{
Jamie Madill007530e2017-12-28 14:27:04 -05003517 if (!context->getExtensions().debugMarker)
3518 {
3519 // The debug marker calls should not set error state
3520 // However, it seems reasonable to set an error state if the extension is not enabled
3521 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3522 return false;
3523 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003524
Jamie Madill007530e2017-12-28 14:27:04 -05003525 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003526 if (length < 0)
3527 {
3528 return false;
3529 }
3530
3531 if (marker == nullptr)
3532 {
3533 return false;
3534 }
3535
3536 return true;
3537}
3538
3539bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3540{
Jamie Madill007530e2017-12-28 14:27:04 -05003541 if (!context->getExtensions().debugMarker)
3542 {
3543 // The debug marker calls should not set error state
3544 // However, it seems reasonable to set an error state if the extension is not enabled
3545 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3546 return false;
3547 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003548
Jamie Madill007530e2017-12-28 14:27:04 -05003549 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003550 if (length < 0)
3551 {
3552 return false;
3553 }
3554
3555 if (length > 0 && marker == nullptr)
3556 {
3557 return false;
3558 }
3559
3560 return true;
3561}
3562
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003563bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003564{
Geoff Langa8406172015-07-21 16:53:39 -04003565 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003567 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003568 return false;
3569 }
3570
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003571 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003572 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003573 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003574 if (!context->getExtensions().eglImage)
3575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003576 context->handleError(InvalidEnum()
3577 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003578 }
3579 break;
3580
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003581 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003582 if (!context->getExtensions().eglImageExternal)
3583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003584 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3585 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003586 }
Geoff Langa8406172015-07-21 16:53:39 -04003587 break;
3588
3589 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003590 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003591 return false;
3592 }
3593
Rafael Cintron05a449a2018-06-20 18:08:04 -07003594 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003595
Jamie Madill61e16b42017-06-19 11:13:23 -04003596 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003597 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003599 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003600 return false;
3601 }
3602
Jamie Madill007530e2017-12-28 14:27:04 -05003603 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003604 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003605 context->handleError(InvalidOperation()
3606 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003607 return false;
3608 }
3609
Geoff Langca271392017-04-05 12:30:00 -04003610 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003611 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003612 if (!textureCaps.texturable)
3613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003614 context->handleError(InvalidOperation()
3615 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003616 return false;
3617 }
3618
Geoff Langdcab33b2015-07-21 13:03:16 -04003619 return true;
3620}
3621
3622bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003623 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003624 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003625{
Geoff Langa8406172015-07-21 16:53:39 -04003626 if (!context->getExtensions().eglImage)
3627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003628 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003629 return false;
3630 }
3631
3632 switch (target)
3633 {
3634 case GL_RENDERBUFFER:
3635 break;
3636
3637 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003638 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003639 return false;
3640 }
3641
Rafael Cintron05a449a2018-06-20 18:08:04 -07003642 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003643
Jamie Madill61e16b42017-06-19 11:13:23 -04003644 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003645 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003647 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003648 return false;
3649 }
3650
Geoff Langca271392017-04-05 12:30:00 -04003651 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003652 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003653 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003655 context->handleError(InvalidOperation()
3656 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003657 return false;
3658 }
3659
Geoff Langdcab33b2015-07-21 13:03:16 -04003660 return true;
3661}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003662
3663bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3664{
Geoff Lang36167ab2015-12-07 10:27:14 -05003665 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003666 {
3667 // The default VAO should always exist
3668 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003669 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003670 return false;
3671 }
3672
3673 return true;
3674}
3675
Geoff Langc5629752015-12-07 16:29:04 -05003676bool ValidateProgramBinaryBase(Context *context,
3677 GLuint program,
3678 GLenum binaryFormat,
3679 const void *binary,
3680 GLint length)
3681{
3682 Program *programObject = GetValidProgram(context, program);
3683 if (programObject == nullptr)
3684 {
3685 return false;
3686 }
3687
3688 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3689 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3690 programBinaryFormats.end())
3691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003692 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003693 return false;
3694 }
3695
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003696 if (context->hasActiveTransformFeedback(program))
3697 {
3698 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003699 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3700 "is associated with an active transform "
3701 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003702 return false;
3703 }
3704
Geoff Langc5629752015-12-07 16:29:04 -05003705 return true;
3706}
3707
3708bool ValidateGetProgramBinaryBase(Context *context,
3709 GLuint program,
3710 GLsizei bufSize,
3711 GLsizei *length,
3712 GLenum *binaryFormat,
3713 void *binary)
3714{
3715 Program *programObject = GetValidProgram(context, program);
3716 if (programObject == nullptr)
3717 {
3718 return false;
3719 }
3720
3721 if (!programObject->isLinked())
3722 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003723 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003724 return false;
3725 }
3726
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003727 if (context->getCaps().programBinaryFormats.empty())
3728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003729 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003730 return false;
3731 }
3732
Geoff Langc5629752015-12-07 16:29:04 -05003733 return true;
3734}
Jamie Madillc29968b2016-01-20 11:17:23 -05003735
Jamie Madill5b772312018-03-08 20:28:32 -05003736bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003737{
3738 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003739 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003740 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003741 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3742 return false;
3743 }
3744 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3745 {
3746 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003747 return false;
3748 }
3749
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003750 ASSERT(context->getGLState().getDrawFramebuffer());
3751 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003752 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3753
3754 // This should come first before the check for the default frame buffer
3755 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3756 // rather than INVALID_OPERATION
3757 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3758 {
3759 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3760
3761 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003762 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3763 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003764 {
3765 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003766 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3767 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3768 // 3.1 is still a bit ambiguous about the error, but future specs are
3769 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003770 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003771 return false;
3772 }
3773 else if (bufs[colorAttachment] >= maxColorAttachment)
3774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003775 context->handleError(InvalidOperation()
3776 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003777 return false;
3778 }
3779 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3780 frameBufferId != 0)
3781 {
3782 // INVALID_OPERATION-GL is bound to buffer and ith argument
3783 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003784 context->handleError(InvalidOperation()
3785 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003786 return false;
3787 }
3788 }
3789
3790 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3791 // and n is not 1 or bufs is bound to value other than BACK and NONE
3792 if (frameBufferId == 0)
3793 {
3794 if (n != 1)
3795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003796 context->handleError(InvalidOperation()
3797 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003798 return false;
3799 }
3800
3801 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003803 context->handleError(
3804 InvalidOperation()
3805 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003806 return false;
3807 }
3808 }
3809
3810 return true;
3811}
3812
Geoff Lang496c02d2016-10-20 11:38:11 -07003813bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003814 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003815 GLenum pname,
3816 GLsizei *length,
3817 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003818{
Geoff Lang496c02d2016-10-20 11:38:11 -07003819 if (length)
3820 {
3821 *length = 0;
3822 }
3823
3824 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3825 {
3826 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003827 InvalidOperation()
3828 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003829 return false;
3830 }
3831
Corentin Walleze4477002017-12-01 14:39:58 -05003832 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003833 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003834 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003835 return false;
3836 }
3837
Geoff Lang496c02d2016-10-20 11:38:11 -07003838 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003839 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003840 case GL_BUFFER_MAP_POINTER:
3841 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003842
Geoff Lang496c02d2016-10-20 11:38:11 -07003843 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003844 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003845 return false;
3846 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003847
3848 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3849 // target bound to zero generate an INVALID_OPERATION error."
3850 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003851 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003853 context->handleError(InvalidOperation()
3854 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003855 return false;
3856 }
3857
Geoff Lang496c02d2016-10-20 11:38:11 -07003858 if (length)
3859 {
3860 *length = 1;
3861 }
3862
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 return true;
3864}
3865
Corentin Wallez336129f2017-10-17 15:55:40 -04003866bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003867{
Corentin Walleze4477002017-12-01 14:39:58 -05003868 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003869 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003870 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003871 return false;
3872 }
3873
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003874 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003875
3876 if (buffer == nullptr || !buffer->isMapped())
3877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003878 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003879 return false;
3880 }
3881
3882 return true;
3883}
3884
3885bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003886 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003887 GLintptr offset,
3888 GLsizeiptr length,
3889 GLbitfield access)
3890{
Corentin Walleze4477002017-12-01 14:39:58 -05003891 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003892 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003893 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003894 return false;
3895 }
3896
Brandon Jones6cad5662017-06-14 13:25:13 -07003897 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003899 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3900 return false;
3901 }
3902
3903 if (length < 0)
3904 {
3905 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003906 return false;
3907 }
3908
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003909 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003910
3911 if (!buffer)
3912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003913 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 return false;
3915 }
3916
3917 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003918 CheckedNumeric<size_t> checkedOffset(offset);
3919 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003920
Jamie Madille2e406c2016-06-02 13:04:10 -04003921 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003923 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003924 return false;
3925 }
3926
3927 // Check for invalid bits in the mask
3928 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3929 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3930 GL_MAP_UNSYNCHRONIZED_BIT;
3931
3932 if (access & ~(allAccessBits))
3933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003934 context->handleError(InvalidValue()
3935 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003936 return false;
3937 }
3938
3939 if (length == 0)
3940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003941 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003942 return false;
3943 }
3944
3945 if (buffer->isMapped())
3946 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003947 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003948 return false;
3949 }
3950
3951 // Check for invalid bit combinations
3952 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003954 context->handleError(InvalidOperation()
3955 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003956 return false;
3957 }
3958
3959 GLbitfield writeOnlyBits =
3960 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3961
3962 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003964 context->handleError(InvalidOperation()
3965 << "Invalid access bits when mapping buffer for reading: 0x"
3966 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003967 return false;
3968 }
3969
3970 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3971 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003972 context->handleError(
3973 InvalidOperation()
3974 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003975 return false;
3976 }
Geoff Lang79f71042017-08-14 16:43:43 -04003977
3978 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003979}
3980
3981bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003982 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003983 GLintptr offset,
3984 GLsizeiptr length)
3985{
Brandon Jones6cad5662017-06-14 13:25:13 -07003986 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003987 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003988 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3989 return false;
3990 }
3991
3992 if (length < 0)
3993 {
3994 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003995 return false;
3996 }
3997
Corentin Walleze4477002017-12-01 14:39:58 -05003998 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004000 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03004001 return false;
4002 }
4003
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004004 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004005
4006 if (buffer == nullptr)
4007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004008 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004009 return false;
4010 }
4011
4012 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004014 context->handleError(InvalidOperation()
4015 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004016 return false;
4017 }
4018
4019 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004020 CheckedNumeric<size_t> checkedOffset(offset);
4021 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004022
Jamie Madille2e406c2016-06-02 13:04:10 -04004023 if (!checkedSize.IsValid() ||
4024 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004026 context->handleError(InvalidValue()
4027 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004028 return false;
4029 }
4030
4031 return true;
4032}
4033
Olli Etuaho41997e72016-03-10 13:38:39 +02004034bool ValidateGenOrDelete(Context *context, GLint n)
4035{
4036 if (n < 0)
4037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004038 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004039 return false;
4040 }
4041 return true;
4042}
4043
Jamie Madill5b772312018-03-08 20:28:32 -05004044bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004045{
4046 if (!context->getExtensions().robustClientMemory)
4047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004048 context->handleError(InvalidOperation()
4049 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004050 return false;
4051 }
4052
4053 if (bufSize < 0)
4054 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004055 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004056 return false;
4057 }
4058
4059 return true;
4060}
4061
Jamie Madill5b772312018-03-08 20:28:32 -05004062bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004063{
4064 if (bufSize < numParams)
4065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004066 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4067 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004068 return false;
4069 }
4070
4071 return true;
4072}
4073
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004074bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004075 GLenum target,
4076 GLenum attachment,
4077 GLenum pname,
4078 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004079{
Geoff Lange8afa902017-09-27 15:00:43 -04004080 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004082 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004083 return false;
4084 }
4085
4086 int clientVersion = context->getClientMajorVersion();
4087
4088 switch (pname)
4089 {
4090 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4091 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4092 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4093 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4094 break;
4095
Martin Radeve5285d22017-07-14 16:23:53 +03004096 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4097 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4098 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4099 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4100 if (clientVersion < 3 || !context->getExtensions().multiview)
4101 {
4102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4103 return false;
4104 }
4105 break;
4106
Geoff Langff5b2d52016-09-07 11:32:23 -04004107 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4108 if (clientVersion < 3 && !context->getExtensions().sRGB)
4109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004110 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004111 return false;
4112 }
4113 break;
4114
4115 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4116 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4117 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4118 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4119 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4120 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4121 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4122 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4123 if (clientVersion < 3)
4124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004125 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004126 return false;
4127 }
4128 break;
4129
Jiawei Shaoa8802472018-05-28 11:17:47 +08004130 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4131 if (!context->getExtensions().geometryShader)
4132 {
4133 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4134 return false;
4135 }
4136 break;
4137
Geoff Langff5b2d52016-09-07 11:32:23 -04004138 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004139 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004140 return false;
4141 }
4142
4143 // Determine if the attachment is a valid enum
4144 switch (attachment)
4145 {
4146 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004147 case GL_DEPTH:
4148 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004149 if (clientVersion < 3)
4150 {
Geoff Langfa125c92017-10-24 13:01:46 -04004151 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004152 return false;
4153 }
4154 break;
4155
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004156 case GL_DEPTH_STENCIL_ATTACHMENT:
4157 if (clientVersion < 3 && !context->isWebGL1())
4158 {
4159 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4160 return false;
4161 }
4162 break;
4163
Geoff Langfa125c92017-10-24 13:01:46 -04004164 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004165 case GL_DEPTH_ATTACHMENT:
4166 case GL_STENCIL_ATTACHMENT:
4167 break;
4168
4169 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004170 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4171 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004172 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4173 {
Geoff Langfa125c92017-10-24 13:01:46 -04004174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004175 return false;
4176 }
4177 break;
4178 }
4179
4180 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4181 ASSERT(framebuffer);
4182
4183 if (framebuffer->id() == 0)
4184 {
4185 if (clientVersion < 3)
4186 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004187 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004188 return false;
4189 }
4190
4191 switch (attachment)
4192 {
4193 case GL_BACK:
4194 case GL_DEPTH:
4195 case GL_STENCIL:
4196 break;
4197
4198 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004200 return false;
4201 }
4202 }
4203 else
4204 {
4205 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4206 {
4207 // Valid attachment query
4208 }
4209 else
4210 {
4211 switch (attachment)
4212 {
4213 case GL_DEPTH_ATTACHMENT:
4214 case GL_STENCIL_ATTACHMENT:
4215 break;
4216
4217 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004218 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004220 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004221 return false;
4222 }
4223 break;
4224
4225 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004227 return false;
4228 }
4229 }
4230 }
4231
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004232 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004233 if (attachmentObject)
4234 {
4235 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4236 attachmentObject->type() == GL_TEXTURE ||
4237 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4238
4239 switch (pname)
4240 {
4241 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4242 if (attachmentObject->type() != GL_RENDERBUFFER &&
4243 attachmentObject->type() != GL_TEXTURE)
4244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004245 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004246 return false;
4247 }
4248 break;
4249
4250 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4251 if (attachmentObject->type() != GL_TEXTURE)
4252 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004253 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004254 return false;
4255 }
4256 break;
4257
4258 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4259 if (attachmentObject->type() != GL_TEXTURE)
4260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004262 return false;
4263 }
4264 break;
4265
4266 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4267 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4268 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004270 return false;
4271 }
4272 break;
4273
4274 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4275 if (attachmentObject->type() != GL_TEXTURE)
4276 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004277 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004278 return false;
4279 }
4280 break;
4281
4282 default:
4283 break;
4284 }
4285 }
4286 else
4287 {
4288 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4289 // is NONE, then querying any other pname will generate INVALID_ENUM.
4290
4291 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4292 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4293 // INVALID_OPERATION for all other pnames
4294
4295 switch (pname)
4296 {
4297 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4298 break;
4299
4300 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4301 if (clientVersion < 3)
4302 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004303 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004304 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004305 return false;
4306 }
4307 break;
4308
4309 default:
4310 if (clientVersion < 3)
4311 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004312 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004313 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004314 return false;
4315 }
4316 else
4317 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004318 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004319 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004320 return false;
4321 }
4322 }
4323 }
4324
Martin Radeve5285d22017-07-14 16:23:53 +03004325 if (numParams)
4326 {
4327 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4328 {
4329 // Only when the viewport offsets are queried we can have a varying number of output
4330 // parameters.
4331 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4332 *numParams = numViews * 2;
4333 }
4334 else
4335 {
4336 // For all other queries we can have only one output parameter.
4337 *numParams = 1;
4338 }
4339 }
4340
Geoff Langff5b2d52016-09-07 11:32:23 -04004341 return true;
4342}
4343
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004344bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004345 GLenum target,
4346 GLenum attachment,
4347 GLenum pname,
4348 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004349 GLsizei *length,
4350 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004351{
4352 if (!ValidateRobustEntryPoint(context, bufSize))
4353 {
4354 return false;
4355 }
4356
Brandon Jonesd1049182018-03-28 10:02:20 -07004357 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004358 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004359 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004360 {
4361 return false;
4362 }
4363
Brandon Jonesd1049182018-03-28 10:02:20 -07004364 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004365 {
4366 return false;
4367 }
4368
Brandon Jonesd1049182018-03-28 10:02:20 -07004369 SetRobustLengthParam(length, numParams);
4370
Geoff Langff5b2d52016-09-07 11:32:23 -04004371 return true;
4372}
4373
Jamie Madill5b772312018-03-08 20:28:32 -05004374bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004375 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004376 GLenum pname,
4377 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004378 GLsizei *length,
4379 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004380{
4381 if (!ValidateRobustEntryPoint(context, bufSize))
4382 {
4383 return false;
4384 }
4385
Brandon Jonesd1049182018-03-28 10:02:20 -07004386 GLsizei numParams = 0;
4387
4388 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004389 {
4390 return false;
4391 }
4392
Brandon Jonesd1049182018-03-28 10:02:20 -07004393 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004394 {
4395 return false;
4396 }
4397
Brandon Jonesd1049182018-03-28 10:02:20 -07004398 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004399 return true;
4400}
4401
Jamie Madill5b772312018-03-08 20:28:32 -05004402bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004403 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004404 GLenum pname,
4405 GLsizei bufSize,
4406 GLsizei *length,
4407 GLint64 *params)
4408{
Brandon Jonesd1049182018-03-28 10:02:20 -07004409 GLsizei numParams = 0;
4410
Geoff Langebebe1c2016-10-14 12:01:31 -04004411 if (!ValidateRobustEntryPoint(context, bufSize))
4412 {
4413 return false;
4414 }
4415
Brandon Jonesd1049182018-03-28 10:02:20 -07004416 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004417 {
4418 return false;
4419 }
4420
Brandon Jonesd1049182018-03-28 10:02:20 -07004421 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004422 {
4423 return false;
4424 }
4425
Brandon Jonesd1049182018-03-28 10:02:20 -07004426 SetRobustLengthParam(length, numParams);
4427
Geoff Langff5b2d52016-09-07 11:32:23 -04004428 return true;
4429}
4430
Jamie Madill5b772312018-03-08 20:28:32 -05004431bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004432{
4433 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004434 if (numParams)
4435 {
4436 *numParams = 1;
4437 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004438
4439 Program *programObject = GetValidProgram(context, program);
4440 if (!programObject)
4441 {
4442 return false;
4443 }
4444
4445 switch (pname)
4446 {
4447 case GL_DELETE_STATUS:
4448 case GL_LINK_STATUS:
4449 case GL_VALIDATE_STATUS:
4450 case GL_INFO_LOG_LENGTH:
4451 case GL_ATTACHED_SHADERS:
4452 case GL_ACTIVE_ATTRIBUTES:
4453 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4454 case GL_ACTIVE_UNIFORMS:
4455 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4456 break;
4457
4458 case GL_PROGRAM_BINARY_LENGTH:
4459 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004461 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4462 "requires GL_OES_get_program_binary or "
4463 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004464 return false;
4465 }
4466 break;
4467
4468 case GL_ACTIVE_UNIFORM_BLOCKS:
4469 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4470 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4471 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4472 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4473 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4474 if (context->getClientMajorVersion() < 3)
4475 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004476 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004477 return false;
4478 }
4479 break;
4480
Yunchao He61afff12017-03-14 15:34:03 +08004481 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004482 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004483 if (context->getClientVersion() < Version(3, 1))
4484 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004485 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004486 return false;
4487 }
4488 break;
4489
Jiawei Shao6ae51612018-02-23 14:03:25 +08004490 case GL_COMPUTE_WORK_GROUP_SIZE:
4491 if (context->getClientVersion() < Version(3, 1))
4492 {
4493 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4494 return false;
4495 }
4496
4497 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4498 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4499 // program which has not been linked successfully, or which does not contain objects to
4500 // form a compute shader.
4501 if (!programObject->isLinked())
4502 {
4503 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4504 return false;
4505 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004506 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004507 {
4508 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4509 return false;
4510 }
4511 break;
4512
Jiawei Shao447bfac2018-03-14 14:23:40 +08004513 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4514 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4515 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4516 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4517 if (!context->getExtensions().geometryShader)
4518 {
4519 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4520 return false;
4521 }
4522
4523 // [EXT_geometry_shader] Chapter 7.12
4524 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4525 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4526 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4527 // successfully, or which does not contain objects to form a geometry shader.
4528 if (!programObject->isLinked())
4529 {
4530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4531 return false;
4532 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004533 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004534 {
4535 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4536 return false;
4537 }
4538 break;
4539
Geoff Langff5b2d52016-09-07 11:32:23 -04004540 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004541 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004542 return false;
4543 }
4544
4545 return true;
4546}
4547
4548bool ValidateGetProgramivRobustANGLE(Context *context,
4549 GLuint program,
4550 GLenum pname,
4551 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004552 GLsizei *length,
4553 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004554{
4555 if (!ValidateRobustEntryPoint(context, bufSize))
4556 {
4557 return false;
4558 }
4559
Brandon Jonesd1049182018-03-28 10:02:20 -07004560 GLsizei numParams = 0;
4561
4562 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004563 {
4564 return false;
4565 }
4566
Brandon Jonesd1049182018-03-28 10:02:20 -07004567 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004568 {
4569 return false;
4570 }
4571
Brandon Jonesd1049182018-03-28 10:02:20 -07004572 SetRobustLengthParam(length, numParams);
4573
Geoff Langff5b2d52016-09-07 11:32:23 -04004574 return true;
4575}
4576
Geoff Lang740d9022016-10-07 11:20:52 -04004577bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4578 GLenum target,
4579 GLenum pname,
4580 GLsizei bufSize,
4581 GLsizei *length,
4582 GLint *params)
4583{
4584 if (!ValidateRobustEntryPoint(context, bufSize))
4585 {
4586 return false;
4587 }
4588
Brandon Jonesd1049182018-03-28 10:02:20 -07004589 GLsizei numParams = 0;
4590
4591 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004592 {
4593 return false;
4594 }
4595
Brandon Jonesd1049182018-03-28 10:02:20 -07004596 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004597 {
4598 return false;
4599 }
4600
Brandon Jonesd1049182018-03-28 10:02:20 -07004601 SetRobustLengthParam(length, numParams);
4602
Geoff Lang740d9022016-10-07 11:20:52 -04004603 return true;
4604}
4605
Geoff Langd7d0ed32016-10-07 11:33:51 -04004606bool ValidateGetShaderivRobustANGLE(Context *context,
4607 GLuint shader,
4608 GLenum pname,
4609 GLsizei bufSize,
4610 GLsizei *length,
4611 GLint *params)
4612{
4613 if (!ValidateRobustEntryPoint(context, bufSize))
4614 {
4615 return false;
4616 }
4617
Brandon Jonesd1049182018-03-28 10:02:20 -07004618 GLsizei numParams = 0;
4619
4620 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004621 {
4622 return false;
4623 }
4624
Brandon Jonesd1049182018-03-28 10:02:20 -07004625 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004626 {
4627 return false;
4628 }
4629
Brandon Jonesd1049182018-03-28 10:02:20 -07004630 SetRobustLengthParam(length, numParams);
4631
Geoff Langd7d0ed32016-10-07 11:33:51 -04004632 return true;
4633}
4634
Geoff Langc1984ed2016-10-07 12:41:00 -04004635bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004636 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004637 GLenum pname,
4638 GLsizei bufSize,
4639 GLsizei *length,
4640 GLfloat *params)
4641{
4642 if (!ValidateRobustEntryPoint(context, bufSize))
4643 {
4644 return false;
4645 }
4646
Brandon Jonesd1049182018-03-28 10:02:20 -07004647 GLsizei numParams = 0;
4648
4649 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004650 {
4651 return false;
4652 }
4653
Brandon Jonesd1049182018-03-28 10:02:20 -07004654 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004655 {
4656 return false;
4657 }
4658
Brandon Jonesd1049182018-03-28 10:02:20 -07004659 SetRobustLengthParam(length, numParams);
4660
Geoff Langc1984ed2016-10-07 12:41:00 -04004661 return true;
4662}
4663
Geoff Langc1984ed2016-10-07 12:41:00 -04004664bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004665 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004666 GLenum pname,
4667 GLsizei bufSize,
4668 GLsizei *length,
4669 GLint *params)
4670{
Brandon Jonesd1049182018-03-28 10:02:20 -07004671
Geoff Langc1984ed2016-10-07 12:41:00 -04004672 if (!ValidateRobustEntryPoint(context, bufSize))
4673 {
4674 return false;
4675 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004676 GLsizei numParams = 0;
4677 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004678 {
4679 return false;
4680 }
4681
Brandon Jonesd1049182018-03-28 10:02:20 -07004682 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004683 {
4684 return false;
4685 }
4686
Brandon Jonesd1049182018-03-28 10:02:20 -07004687 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004688 return true;
4689}
4690
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004691bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4692 TextureType target,
4693 GLenum pname,
4694 GLsizei bufSize,
4695 GLsizei *length,
4696 GLint *params)
4697{
4698 UNIMPLEMENTED();
4699 return false;
4700}
4701
4702bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4703 TextureType target,
4704 GLenum pname,
4705 GLsizei bufSize,
4706 GLsizei *length,
4707 GLuint *params)
4708{
4709 UNIMPLEMENTED();
4710 return false;
4711}
4712
Geoff Langc1984ed2016-10-07 12:41:00 -04004713bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004714 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004715 GLenum pname,
4716 GLsizei bufSize,
4717 const GLfloat *params)
4718{
4719 if (!ValidateRobustEntryPoint(context, bufSize))
4720 {
4721 return false;
4722 }
4723
4724 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4725}
4726
Geoff Langc1984ed2016-10-07 12:41:00 -04004727bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004728 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004729 GLenum pname,
4730 GLsizei bufSize,
4731 const GLint *params)
4732{
4733 if (!ValidateRobustEntryPoint(context, bufSize))
4734 {
4735 return false;
4736 }
4737
4738 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4739}
4740
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004741bool ValidateTexParameterIivRobustANGLE(Context *context,
4742 TextureType target,
4743 GLenum pname,
4744 GLsizei bufSize,
4745 const GLint *params)
4746{
4747 UNIMPLEMENTED();
4748 return false;
4749}
4750
4751bool ValidateTexParameterIuivRobustANGLE(Context *context,
4752 TextureType target,
4753 GLenum pname,
4754 GLsizei bufSize,
4755 const GLuint *params)
4756{
4757 UNIMPLEMENTED();
4758 return false;
4759}
4760
Geoff Langc1984ed2016-10-07 12:41:00 -04004761bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4762 GLuint sampler,
4763 GLenum pname,
4764 GLuint bufSize,
4765 GLsizei *length,
4766 GLfloat *params)
4767{
4768 if (!ValidateRobustEntryPoint(context, bufSize))
4769 {
4770 return false;
4771 }
4772
Brandon Jonesd1049182018-03-28 10:02:20 -07004773 GLsizei numParams = 0;
4774
4775 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004776 {
4777 return false;
4778 }
4779
Brandon Jonesd1049182018-03-28 10:02:20 -07004780 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004781 {
4782 return false;
4783 }
4784
Brandon Jonesd1049182018-03-28 10:02:20 -07004785 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004786 return true;
4787}
4788
Geoff Langc1984ed2016-10-07 12:41:00 -04004789bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4790 GLuint sampler,
4791 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004792 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004793 GLsizei *length,
4794 GLint *params)
4795{
4796 if (!ValidateRobustEntryPoint(context, bufSize))
4797 {
4798 return false;
4799 }
4800
Brandon Jonesd1049182018-03-28 10:02:20 -07004801 GLsizei numParams = 0;
4802
4803 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004804 {
4805 return false;
4806 }
4807
Brandon Jonesd1049182018-03-28 10:02:20 -07004808 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004809 {
4810 return false;
4811 }
4812
Brandon Jonesd1049182018-03-28 10:02:20 -07004813 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004814 return true;
4815}
4816
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004817bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4818 GLuint sampler,
4819 GLenum pname,
4820 GLsizei bufSize,
4821 GLsizei *length,
4822 GLint *params)
4823{
4824 UNIMPLEMENTED();
4825 return false;
4826}
4827
4828bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4829 GLuint sampler,
4830 GLenum pname,
4831 GLsizei bufSize,
4832 GLsizei *length,
4833 GLuint *params)
4834{
4835 UNIMPLEMENTED();
4836 return false;
4837}
4838
Geoff Langc1984ed2016-10-07 12:41:00 -04004839bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4840 GLuint sampler,
4841 GLenum pname,
4842 GLsizei bufSize,
4843 const GLfloat *params)
4844{
4845 if (!ValidateRobustEntryPoint(context, bufSize))
4846 {
4847 return false;
4848 }
4849
4850 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4851}
4852
Geoff Langc1984ed2016-10-07 12:41:00 -04004853bool ValidateSamplerParameterivRobustANGLE(Context *context,
4854 GLuint sampler,
4855 GLenum pname,
4856 GLsizei bufSize,
4857 const GLint *params)
4858{
4859 if (!ValidateRobustEntryPoint(context, bufSize))
4860 {
4861 return false;
4862 }
4863
4864 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4865}
4866
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004867bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4868 GLuint sampler,
4869 GLenum pname,
4870 GLsizei bufSize,
4871 const GLint *param)
4872{
4873 UNIMPLEMENTED();
4874 return false;
4875}
4876
4877bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4878 GLuint sampler,
4879 GLenum pname,
4880 GLsizei bufSize,
4881 const GLuint *param)
4882{
4883 UNIMPLEMENTED();
4884 return false;
4885}
4886
Geoff Lang0b031062016-10-13 14:30:04 -04004887bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4888 GLuint index,
4889 GLenum pname,
4890 GLsizei bufSize,
4891 GLsizei *length,
4892 GLfloat *params)
4893{
4894 if (!ValidateRobustEntryPoint(context, bufSize))
4895 {
4896 return false;
4897 }
4898
Brandon Jonesd1049182018-03-28 10:02:20 -07004899 GLsizei writeLength = 0;
4900
4901 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004902 {
4903 return false;
4904 }
4905
Brandon Jonesd1049182018-03-28 10:02:20 -07004906 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004907 {
4908 return false;
4909 }
4910
Brandon Jonesd1049182018-03-28 10:02:20 -07004911 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004912 return true;
4913}
4914
Geoff Lang0b031062016-10-13 14:30:04 -04004915bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4916 GLuint index,
4917 GLenum pname,
4918 GLsizei bufSize,
4919 GLsizei *length,
4920 GLint *params)
4921{
4922 if (!ValidateRobustEntryPoint(context, bufSize))
4923 {
4924 return false;
4925 }
4926
Brandon Jonesd1049182018-03-28 10:02:20 -07004927 GLsizei writeLength = 0;
4928
4929 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004930 {
4931 return false;
4932 }
4933
Brandon Jonesd1049182018-03-28 10:02:20 -07004934 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004935 {
4936 return false;
4937 }
4938
Brandon Jonesd1049182018-03-28 10:02:20 -07004939 SetRobustLengthParam(length, writeLength);
4940
Geoff Lang0b031062016-10-13 14:30:04 -04004941 return true;
4942}
4943
Geoff Lang0b031062016-10-13 14:30:04 -04004944bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4945 GLuint index,
4946 GLenum pname,
4947 GLsizei bufSize,
4948 GLsizei *length,
4949 void **pointer)
4950{
4951 if (!ValidateRobustEntryPoint(context, bufSize))
4952 {
4953 return false;
4954 }
4955
Brandon Jonesd1049182018-03-28 10:02:20 -07004956 GLsizei writeLength = 0;
4957
4958 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004959 {
4960 return false;
4961 }
4962
Brandon Jonesd1049182018-03-28 10:02:20 -07004963 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004964 {
4965 return false;
4966 }
4967
Brandon Jonesd1049182018-03-28 10:02:20 -07004968 SetRobustLengthParam(length, writeLength);
4969
Geoff Lang0b031062016-10-13 14:30:04 -04004970 return true;
4971}
4972
Geoff Lang0b031062016-10-13 14:30:04 -04004973bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4974 GLuint index,
4975 GLenum pname,
4976 GLsizei bufSize,
4977 GLsizei *length,
4978 GLint *params)
4979{
4980 if (!ValidateRobustEntryPoint(context, bufSize))
4981 {
4982 return false;
4983 }
4984
Brandon Jonesd1049182018-03-28 10:02:20 -07004985 GLsizei writeLength = 0;
4986
4987 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004988 {
4989 return false;
4990 }
4991
Brandon Jonesd1049182018-03-28 10:02:20 -07004992 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004993 {
4994 return false;
4995 }
4996
Brandon Jonesd1049182018-03-28 10:02:20 -07004997 SetRobustLengthParam(length, writeLength);
4998
Geoff Lang0b031062016-10-13 14:30:04 -04004999 return true;
5000}
5001
Geoff Lang0b031062016-10-13 14:30:04 -04005002bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5003 GLuint index,
5004 GLenum pname,
5005 GLsizei bufSize,
5006 GLsizei *length,
5007 GLuint *params)
5008{
5009 if (!ValidateRobustEntryPoint(context, bufSize))
5010 {
5011 return false;
5012 }
5013
Brandon Jonesd1049182018-03-28 10:02:20 -07005014 GLsizei writeLength = 0;
5015
5016 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005017 {
5018 return false;
5019 }
5020
Brandon Jonesd1049182018-03-28 10:02:20 -07005021 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005022 {
5023 return false;
5024 }
5025
Brandon Jonesd1049182018-03-28 10:02:20 -07005026 SetRobustLengthParam(length, writeLength);
5027
Geoff Lang0b031062016-10-13 14:30:04 -04005028 return true;
5029}
5030
Geoff Lang6899b872016-10-14 11:30:13 -04005031bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5032 GLuint program,
5033 GLuint uniformBlockIndex,
5034 GLenum pname,
5035 GLsizei bufSize,
5036 GLsizei *length,
5037 GLint *params)
5038{
5039 if (!ValidateRobustEntryPoint(context, bufSize))
5040 {
5041 return false;
5042 }
5043
Brandon Jonesd1049182018-03-28 10:02:20 -07005044 GLsizei writeLength = 0;
5045
5046 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5047 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005048 {
5049 return false;
5050 }
5051
Brandon Jonesd1049182018-03-28 10:02:20 -07005052 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005053 {
5054 return false;
5055 }
5056
Brandon Jonesd1049182018-03-28 10:02:20 -07005057 SetRobustLengthParam(length, writeLength);
5058
Geoff Lang6899b872016-10-14 11:30:13 -04005059 return true;
5060}
5061
Brandon Jones416aaf92018-04-10 08:10:16 -07005062bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005063 GLenum target,
5064 GLenum internalformat,
5065 GLenum pname,
5066 GLsizei bufSize,
5067 GLsizei *length,
5068 GLint *params)
5069{
5070 if (!ValidateRobustEntryPoint(context, bufSize))
5071 {
5072 return false;
5073 }
5074
Brandon Jonesd1049182018-03-28 10:02:20 -07005075 GLsizei numParams = 0;
5076
5077 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5078 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005079 {
5080 return false;
5081 }
5082
Brandon Jonesd1049182018-03-28 10:02:20 -07005083 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005084 {
5085 return false;
5086 }
5087
Brandon Jonesd1049182018-03-28 10:02:20 -07005088 SetRobustLengthParam(length, numParams);
5089
Geoff Lang0a9661f2016-10-20 10:59:20 -07005090 return true;
5091}
5092
Jamie Madill5b772312018-03-08 20:28:32 -05005093bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005094 GLuint attribIndex,
5095 GLint size,
5096 GLenum type,
5097 GLboolean pureInteger)
5098{
5099 const Caps &caps = context->getCaps();
5100 if (attribIndex >= caps.maxVertexAttributes)
5101 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005102 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005103 return false;
5104 }
5105
5106 if (size < 1 || size > 4)
5107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005108 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005109 return false;
Shao80957d92017-02-20 21:25:59 +08005110 }
5111
5112 switch (type)
5113 {
5114 case GL_BYTE:
5115 case GL_UNSIGNED_BYTE:
5116 case GL_SHORT:
5117 case GL_UNSIGNED_SHORT:
5118 break;
5119
5120 case GL_INT:
5121 case GL_UNSIGNED_INT:
5122 if (context->getClientMajorVersion() < 3)
5123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005124 context->handleError(InvalidEnum()
5125 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005126 return false;
5127 }
5128 break;
5129
5130 case GL_FIXED:
5131 case GL_FLOAT:
5132 if (pureInteger)
5133 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005134 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005135 return false;
5136 }
5137 break;
5138
5139 case GL_HALF_FLOAT:
5140 if (context->getClientMajorVersion() < 3)
5141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005142 context->handleError(InvalidEnum()
5143 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005144 return false;
5145 }
5146 if (pureInteger)
5147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005149 return false;
5150 }
5151 break;
5152
5153 case GL_INT_2_10_10_10_REV:
5154 case GL_UNSIGNED_INT_2_10_10_10_REV:
5155 if (context->getClientMajorVersion() < 3)
5156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005157 context->handleError(InvalidEnum()
5158 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005159 return false;
5160 }
5161 if (pureInteger)
5162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005163 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005164 return false;
5165 }
5166 if (size != 4)
5167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005168 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5169 "UNSIGNED_INT_2_10_10_10_REV and "
5170 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005171 return false;
5172 }
5173 break;
5174
5175 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005177 return false;
5178 }
5179
5180 return true;
5181}
5182
Geoff Lang76e65652017-03-27 14:58:02 -04005183// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5184// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5185// specified clear value and the type of a buffer that is being cleared generates an
5186// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005187bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005188 GLint drawbuffer,
5189 const GLenum *validComponentTypes,
5190 size_t validComponentTypeCount)
5191{
5192 const FramebufferAttachment *attachment =
5193 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5194 if (attachment)
5195 {
5196 GLenum componentType = attachment->getFormat().info->componentType;
5197 const GLenum *end = validComponentTypes + validComponentTypeCount;
5198 if (std::find(validComponentTypes, end, componentType) == end)
5199 {
5200 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005201 InvalidOperation()
5202 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005203 return false;
5204 }
5205 }
5206
5207 return true;
5208}
5209
Jamie Madill5b772312018-03-08 20:28:32 -05005210bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005211{
5212 if (!ValidateRobustEntryPoint(context, dataSize))
5213 {
5214 return false;
5215 }
5216
Corentin Wallez336129f2017-10-17 15:55:40 -04005217 gl::Buffer *pixelUnpackBuffer =
5218 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005219 if (pixelUnpackBuffer == nullptr)
5220 {
5221 if (dataSize < imageSize)
5222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005223 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005224 }
5225 }
5226 return true;
5227}
5228
Jamie Madill5b772312018-03-08 20:28:32 -05005229bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005230 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005231 GLenum pname,
5232 bool pointerVersion,
5233 GLsizei *numParams)
5234{
5235 if (numParams)
5236 {
5237 *numParams = 0;
5238 }
5239
Corentin Walleze4477002017-12-01 14:39:58 -05005240 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005241 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005242 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005243 return false;
5244 }
5245
5246 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5247 if (!buffer)
5248 {
5249 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005251 return false;
5252 }
5253
5254 const Extensions &extensions = context->getExtensions();
5255
5256 switch (pname)
5257 {
5258 case GL_BUFFER_USAGE:
5259 case GL_BUFFER_SIZE:
5260 break;
5261
5262 case GL_BUFFER_ACCESS_OES:
5263 if (!extensions.mapBuffer)
5264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005265 context->handleError(InvalidEnum()
5266 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005267 return false;
5268 }
5269 break;
5270
5271 case GL_BUFFER_MAPPED:
5272 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5273 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5274 !extensions.mapBufferRange)
5275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005276 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5277 "GL_OES_mapbuffer or "
5278 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005279 return false;
5280 }
5281 break;
5282
5283 case GL_BUFFER_MAP_POINTER:
5284 if (!pointerVersion)
5285 {
5286 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005287 InvalidEnum()
5288 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005289 return false;
5290 }
5291 break;
5292
5293 case GL_BUFFER_ACCESS_FLAGS:
5294 case GL_BUFFER_MAP_OFFSET:
5295 case GL_BUFFER_MAP_LENGTH:
5296 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5297 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005298 context->handleError(InvalidEnum()
5299 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005300 return false;
5301 }
5302 break;
5303
5304 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005306 return false;
5307 }
5308
5309 // All buffer parameter queries return one value.
5310 if (numParams)
5311 {
5312 *numParams = 1;
5313 }
5314
5315 return true;
5316}
5317
5318bool ValidateGetRenderbufferParameterivBase(Context *context,
5319 GLenum target,
5320 GLenum pname,
5321 GLsizei *length)
5322{
5323 if (length)
5324 {
5325 *length = 0;
5326 }
5327
5328 if (target != GL_RENDERBUFFER)
5329 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005330 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005331 return false;
5332 }
5333
5334 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5335 if (renderbuffer == nullptr)
5336 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005337 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005338 return false;
5339 }
5340
5341 switch (pname)
5342 {
5343 case GL_RENDERBUFFER_WIDTH:
5344 case GL_RENDERBUFFER_HEIGHT:
5345 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5346 case GL_RENDERBUFFER_RED_SIZE:
5347 case GL_RENDERBUFFER_GREEN_SIZE:
5348 case GL_RENDERBUFFER_BLUE_SIZE:
5349 case GL_RENDERBUFFER_ALPHA_SIZE:
5350 case GL_RENDERBUFFER_DEPTH_SIZE:
5351 case GL_RENDERBUFFER_STENCIL_SIZE:
5352 break;
5353
5354 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5355 if (!context->getExtensions().framebufferMultisample)
5356 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005358 return false;
5359 }
5360 break;
5361
5362 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005364 return false;
5365 }
5366
5367 if (length)
5368 {
5369 *length = 1;
5370 }
5371 return true;
5372}
5373
5374bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5375{
5376 if (length)
5377 {
5378 *length = 0;
5379 }
5380
5381 if (GetValidShader(context, shader) == nullptr)
5382 {
5383 return false;
5384 }
5385
5386 switch (pname)
5387 {
5388 case GL_SHADER_TYPE:
5389 case GL_DELETE_STATUS:
5390 case GL_COMPILE_STATUS:
5391 case GL_INFO_LOG_LENGTH:
5392 case GL_SHADER_SOURCE_LENGTH:
5393 break;
5394
5395 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5396 if (!context->getExtensions().translatedShaderSource)
5397 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005399 return false;
5400 }
5401 break;
5402
5403 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005404 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005405 return false;
5406 }
5407
5408 if (length)
5409 {
5410 *length = 1;
5411 }
5412 return true;
5413}
5414
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005415bool ValidateGetTexParameterBase(Context *context,
5416 TextureType target,
5417 GLenum pname,
5418 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005419{
5420 if (length)
5421 {
5422 *length = 0;
5423 }
5424
5425 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5426 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005427 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005428 return false;
5429 }
5430
5431 if (context->getTargetTexture(target) == nullptr)
5432 {
5433 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005434 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005435 return false;
5436 }
5437
5438 switch (pname)
5439 {
5440 case GL_TEXTURE_MAG_FILTER:
5441 case GL_TEXTURE_MIN_FILTER:
5442 case GL_TEXTURE_WRAP_S:
5443 case GL_TEXTURE_WRAP_T:
5444 break;
5445
5446 case GL_TEXTURE_USAGE_ANGLE:
5447 if (!context->getExtensions().textureUsage)
5448 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005450 return false;
5451 }
5452 break;
5453
5454 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005455 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005456 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005457 return false;
5458 }
5459 break;
5460
5461 case GL_TEXTURE_IMMUTABLE_FORMAT:
5462 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5463 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005464 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005465 return false;
5466 }
5467 break;
5468
5469 case GL_TEXTURE_WRAP_R:
5470 case GL_TEXTURE_IMMUTABLE_LEVELS:
5471 case GL_TEXTURE_SWIZZLE_R:
5472 case GL_TEXTURE_SWIZZLE_G:
5473 case GL_TEXTURE_SWIZZLE_B:
5474 case GL_TEXTURE_SWIZZLE_A:
5475 case GL_TEXTURE_BASE_LEVEL:
5476 case GL_TEXTURE_MAX_LEVEL:
5477 case GL_TEXTURE_MIN_LOD:
5478 case GL_TEXTURE_MAX_LOD:
5479 case GL_TEXTURE_COMPARE_MODE:
5480 case GL_TEXTURE_COMPARE_FUNC:
5481 if (context->getClientMajorVersion() < 3)
5482 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005483 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486 break;
5487
5488 case GL_TEXTURE_SRGB_DECODE_EXT:
5489 if (!context->getExtensions().textureSRGBDecode)
5490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005491 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 return false;
5493 }
5494 break;
5495
Yunchao Hebacaa712018-01-30 14:01:39 +08005496 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5497 if (context->getClientVersion() < Version(3, 1))
5498 {
5499 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5500 return false;
5501 }
5502 break;
5503
Jamie Madillbe849e42017-05-02 15:49:00 -04005504 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005505 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005506 return false;
5507 }
5508
5509 if (length)
5510 {
5511 *length = 1;
5512 }
5513 return true;
5514}
5515
5516bool ValidateGetVertexAttribBase(Context *context,
5517 GLuint index,
5518 GLenum pname,
5519 GLsizei *length,
5520 bool pointer,
5521 bool pureIntegerEntryPoint)
5522{
5523 if (length)
5524 {
5525 *length = 0;
5526 }
5527
5528 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005530 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005531 return false;
5532 }
5533
5534 if (index >= context->getCaps().maxVertexAttributes)
5535 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005536 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005537 return false;
5538 }
5539
5540 if (pointer)
5541 {
5542 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5543 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005544 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005545 return false;
5546 }
5547 }
5548 else
5549 {
5550 switch (pname)
5551 {
5552 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5553 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5554 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5555 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5556 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5557 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5558 case GL_CURRENT_VERTEX_ATTRIB:
5559 break;
5560
5561 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5562 static_assert(
5563 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5564 "ANGLE extension enums not equal to GL enums.");
5565 if (context->getClientMajorVersion() < 3 &&
5566 !context->getExtensions().instancedArrays)
5567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005568 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5569 "requires OpenGL ES 3.0 or "
5570 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005571 return false;
5572 }
5573 break;
5574
5575 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5576 if (context->getClientMajorVersion() < 3)
5577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005578 context->handleError(
5579 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005580 return false;
5581 }
5582 break;
5583
5584 case GL_VERTEX_ATTRIB_BINDING:
5585 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5586 if (context->getClientVersion() < ES_3_1)
5587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005588 context->handleError(InvalidEnum()
5589 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005590 return false;
5591 }
5592 break;
5593
5594 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005595 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005596 return false;
5597 }
5598 }
5599
5600 if (length)
5601 {
5602 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5603 {
5604 *length = 4;
5605 }
5606 else
5607 {
5608 *length = 1;
5609 }
5610 }
5611
5612 return true;
5613}
5614
Jamie Madill4928b7c2017-06-20 12:57:39 -04005615bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005616 GLint x,
5617 GLint y,
5618 GLsizei width,
5619 GLsizei height,
5620 GLenum format,
5621 GLenum type,
5622 GLsizei bufSize,
5623 GLsizei *length,
5624 GLsizei *columns,
5625 GLsizei *rows,
5626 void *pixels)
5627{
5628 if (length != nullptr)
5629 {
5630 *length = 0;
5631 }
5632 if (rows != nullptr)
5633 {
5634 *rows = 0;
5635 }
5636 if (columns != nullptr)
5637 {
5638 *columns = 0;
5639 }
5640
5641 if (width < 0 || height < 0)
5642 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005643 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005644 return false;
5645 }
5646
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005647 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005648
Jamie Madill427064d2018-04-13 16:20:34 -04005649 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005650 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005651 return false;
5652 }
5653
Jamie Madille98b1b52018-03-08 09:47:23 -05005654 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005655 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005656 return false;
5657 }
5658
Jamie Madill690c8eb2018-03-12 15:20:03 -04005659 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 ASSERT(framebuffer);
5661
5662 if (framebuffer->getReadBufferState() == GL_NONE)
5663 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005664 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005665 return false;
5666 }
5667
5668 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5669 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5670 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5671 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5672 // situation is an application error that would lead to a crash in ANGLE.
5673 if (readBuffer == nullptr)
5674 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005675 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005676 return false;
5677 }
5678
Martin Radev28031682017-07-28 14:47:56 +03005679 // ANGLE_multiview, Revision 1:
5680 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5681 // current read framebuffer is not NONE.
5682 if (readBuffer->getMultiviewLayout() != GL_NONE)
5683 {
5684 context->handleError(InvalidFramebufferOperation()
5685 << "Attempting to read from a multi-view framebuffer.");
5686 return false;
5687 }
5688
Geoff Lang280ba992017-04-18 16:30:58 -04005689 if (context->getExtensions().webglCompatibility)
5690 {
5691 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5692 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5693 // and type before validating the combination of format and type. However, the
5694 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5695 // verifies that GL_INVALID_OPERATION is generated.
5696 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5697 // dEQP/WebGL.
5698 if (!ValidReadPixelsFormatEnum(context, format))
5699 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005700 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005701 return false;
5702 }
5703
5704 if (!ValidReadPixelsTypeEnum(context, type))
5705 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005706 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005707 return false;
5708 }
5709 }
5710
Jamie Madill690c8eb2018-03-12 15:20:03 -04005711 GLenum currentFormat = GL_NONE;
5712 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5713
5714 GLenum currentType = GL_NONE;
5715 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5716
Jamie Madillbe849e42017-05-02 15:49:00 -04005717 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5718
5719 bool validFormatTypeCombination =
5720 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5721
5722 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5723 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005724 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005725 return false;
5726 }
5727
5728 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005729 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005730 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5731 {
5732 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005733 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005734 return false;
5735 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005736 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5737 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5738 {
5739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5740 return false;
5741 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005742
5743 // .. the data would be packed to the buffer object such that the memory writes required
5744 // would exceed the data store size.
5745 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5746 const gl::Extents size(width, height, 1);
5747 const auto &pack = context->getGLState().getPackState();
5748
5749 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5750 if (endByteOrErr.isError())
5751 {
5752 context->handleError(endByteOrErr.getError());
5753 return false;
5754 }
5755
5756 size_t endByte = endByteOrErr.getResult();
5757 if (bufSize >= 0)
5758 {
5759 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5760 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005761 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005762 return false;
5763 }
5764 }
5765
5766 if (pixelPackBuffer != nullptr)
5767 {
5768 CheckedNumeric<size_t> checkedEndByte(endByte);
5769 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5770 checkedEndByte += checkedOffset;
5771
5772 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5773 {
5774 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005775 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005776 return false;
5777 }
5778 }
5779
5780 if (pixelPackBuffer == nullptr && length != nullptr)
5781 {
5782 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5783 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005784 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005785 return false;
5786 }
5787
5788 *length = static_cast<GLsizei>(endByte);
5789 }
5790
Geoff Langa953b522018-02-21 16:56:23 -05005791 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005792 angle::CheckedNumeric<int> clippedExtent(length);
5793 if (start < 0)
5794 {
5795 // "subtract" the area that is less than 0
5796 clippedExtent += start;
5797 }
5798
Geoff Langa953b522018-02-21 16:56:23 -05005799 angle::CheckedNumeric<int> readExtent = start;
5800 readExtent += length;
5801 if (!readExtent.IsValid())
5802 {
5803 return false;
5804 }
5805
5806 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 {
5808 // Subtract the region to the right of the read buffer
5809 clippedExtent -= (readExtent - bufferSize);
5810 }
5811
5812 if (!clippedExtent.IsValid())
5813 {
Geoff Langa953b522018-02-21 16:56:23 -05005814 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 }
5816
Geoff Langa953b522018-02-21 16:56:23 -05005817 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5818 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005819 };
5820
Geoff Langa953b522018-02-21 16:56:23 -05005821 GLsizei writtenColumns = 0;
5822 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5823 {
5824 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5825 return false;
5826 }
5827
5828 GLsizei writtenRows = 0;
5829 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5830 {
5831 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5832 return false;
5833 }
5834
Jamie Madillbe849e42017-05-02 15:49:00 -04005835 if (columns != nullptr)
5836 {
Geoff Langa953b522018-02-21 16:56:23 -05005837 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005838 }
5839
5840 if (rows != nullptr)
5841 {
Geoff Langa953b522018-02-21 16:56:23 -05005842 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005843 }
5844
5845 return true;
5846}
5847
5848template <typename ParamType>
5849bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005850 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005851 GLenum pname,
5852 GLsizei bufSize,
5853 const ParamType *params)
5854{
5855 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005857 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005858 return false;
5859 }
5860
5861 if (context->getTargetTexture(target) == nullptr)
5862 {
5863 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005864 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005865 return false;
5866 }
5867
5868 const GLsizei minBufSize = 1;
5869 if (bufSize >= 0 && bufSize < minBufSize)
5870 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005871 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005872 return false;
5873 }
5874
5875 switch (pname)
5876 {
5877 case GL_TEXTURE_WRAP_R:
5878 case GL_TEXTURE_SWIZZLE_R:
5879 case GL_TEXTURE_SWIZZLE_G:
5880 case GL_TEXTURE_SWIZZLE_B:
5881 case GL_TEXTURE_SWIZZLE_A:
5882 case GL_TEXTURE_BASE_LEVEL:
5883 case GL_TEXTURE_MAX_LEVEL:
5884 case GL_TEXTURE_COMPARE_MODE:
5885 case GL_TEXTURE_COMPARE_FUNC:
5886 case GL_TEXTURE_MIN_LOD:
5887 case GL_TEXTURE_MAX_LOD:
5888 if (context->getClientMajorVersion() < 3)
5889 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005890 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005891 return false;
5892 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005893 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005895 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5896 "available without "
5897 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005898 return false;
5899 }
5900 break;
5901
5902 default:
5903 break;
5904 }
5905
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005906 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005907 {
5908 switch (pname)
5909 {
5910 case GL_TEXTURE_MIN_FILTER:
5911 case GL_TEXTURE_MAG_FILTER:
5912 case GL_TEXTURE_WRAP_S:
5913 case GL_TEXTURE_WRAP_T:
5914 case GL_TEXTURE_WRAP_R:
5915 case GL_TEXTURE_MIN_LOD:
5916 case GL_TEXTURE_MAX_LOD:
5917 case GL_TEXTURE_COMPARE_MODE:
5918 case GL_TEXTURE_COMPARE_FUNC:
5919 context->handleError(InvalidEnum()
5920 << "Invalid parameter for 2D multisampled textures.");
5921 return false;
5922 }
5923 }
5924
Jamie Madillbe849e42017-05-02 15:49:00 -04005925 switch (pname)
5926 {
5927 case GL_TEXTURE_WRAP_S:
5928 case GL_TEXTURE_WRAP_T:
5929 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005930 {
5931 bool restrictedWrapModes =
5932 target == TextureType::External || target == TextureType::Rectangle;
5933 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005934 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005935 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005936 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005937 }
5938 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005939
5940 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005941 {
5942 bool restrictedMinFilter =
5943 target == TextureType::External || target == TextureType::Rectangle;
5944 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005945 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005946 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005947 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005948 }
5949 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005950
5951 case GL_TEXTURE_MAG_FILTER:
5952 if (!ValidateTextureMagFilterValue(context, params))
5953 {
5954 return false;
5955 }
5956 break;
5957
5958 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005959 if (!context->getExtensions().textureUsage)
5960 {
5961 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5962 return false;
5963 }
5964
Jamie Madillbe849e42017-05-02 15:49:00 -04005965 switch (ConvertToGLenum(params[0]))
5966 {
5967 case GL_NONE:
5968 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5969 break;
5970
5971 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005972 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005973 return false;
5974 }
5975 break;
5976
5977 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005978 {
5979 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5980 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005981 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005982 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005983 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005984 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5985 }
5986 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005987
5988 case GL_TEXTURE_MIN_LOD:
5989 case GL_TEXTURE_MAX_LOD:
5990 // any value is permissible
5991 break;
5992
5993 case GL_TEXTURE_COMPARE_MODE:
5994 if (!ValidateTextureCompareModeValue(context, params))
5995 {
5996 return false;
5997 }
5998 break;
5999
6000 case GL_TEXTURE_COMPARE_FUNC:
6001 if (!ValidateTextureCompareFuncValue(context, params))
6002 {
6003 return false;
6004 }
6005 break;
6006
6007 case GL_TEXTURE_SWIZZLE_R:
6008 case GL_TEXTURE_SWIZZLE_G:
6009 case GL_TEXTURE_SWIZZLE_B:
6010 case GL_TEXTURE_SWIZZLE_A:
6011 switch (ConvertToGLenum(params[0]))
6012 {
6013 case GL_RED:
6014 case GL_GREEN:
6015 case GL_BLUE:
6016 case GL_ALPHA:
6017 case GL_ZERO:
6018 case GL_ONE:
6019 break;
6020
6021 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006023 return false;
6024 }
6025 break;
6026
6027 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006028 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006030 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006031 return false;
6032 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006033 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006035 context->handleError(InvalidOperation()
6036 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006037 return false;
6038 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006039 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006040 {
6041 context->handleError(InvalidOperation()
6042 << "Base level must be 0 for multisampled textures.");
6043 return false;
6044 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006045 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006046 {
6047 context->handleError(InvalidOperation()
6048 << "Base level must be 0 for rectangle textures.");
6049 return false;
6050 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006051 break;
6052
6053 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006054 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006055 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006056 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006057 return false;
6058 }
6059 break;
6060
6061 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6062 if (context->getClientVersion() < Version(3, 1))
6063 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006064 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006065 return false;
6066 }
6067 switch (ConvertToGLenum(params[0]))
6068 {
6069 case GL_DEPTH_COMPONENT:
6070 case GL_STENCIL_INDEX:
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 break;
6078
6079 case GL_TEXTURE_SRGB_DECODE_EXT:
6080 if (!ValidateTextureSRGBDecodeValue(context, params))
6081 {
6082 return false;
6083 }
6084 break;
6085
6086 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006087 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006088 return false;
6089 }
6090
6091 return true;
6092}
6093
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006094template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6095template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006096
Jamie Madill5b772312018-03-08 20:28:32 -05006097bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006098{
6099 if (index >= MAX_VERTEX_ATTRIBS)
6100 {
6101 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6102 return false;
6103 }
6104
6105 return true;
6106}
6107
6108bool ValidateGetActiveUniformBlockivBase(Context *context,
6109 GLuint program,
6110 GLuint uniformBlockIndex,
6111 GLenum pname,
6112 GLsizei *length)
6113{
6114 if (length)
6115 {
6116 *length = 0;
6117 }
6118
6119 if (context->getClientMajorVersion() < 3)
6120 {
6121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6122 return false;
6123 }
6124
6125 Program *programObject = GetValidProgram(context, program);
6126 if (!programObject)
6127 {
6128 return false;
6129 }
6130
6131 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6132 {
6133 context->handleError(InvalidValue()
6134 << "uniformBlockIndex exceeds active uniform block count.");
6135 return false;
6136 }
6137
6138 switch (pname)
6139 {
6140 case GL_UNIFORM_BLOCK_BINDING:
6141 case GL_UNIFORM_BLOCK_DATA_SIZE:
6142 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6143 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6144 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6145 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6146 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6147 break;
6148
6149 default:
6150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6151 return false;
6152 }
6153
6154 if (length)
6155 {
6156 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6157 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006158 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006159 programObject->getUniformBlockByIndex(uniformBlockIndex);
6160 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6161 }
6162 else
6163 {
6164 *length = 1;
6165 }
6166 }
6167
6168 return true;
6169}
6170
Jamie Madill9696d072017-08-26 23:19:57 -04006171template <typename ParamType>
6172bool ValidateSamplerParameterBase(Context *context,
6173 GLuint sampler,
6174 GLenum pname,
6175 GLsizei bufSize,
6176 ParamType *params)
6177{
6178 if (context->getClientMajorVersion() < 3)
6179 {
6180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6181 return false;
6182 }
6183
6184 if (!context->isSampler(sampler))
6185 {
6186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6187 return false;
6188 }
6189
6190 const GLsizei minBufSize = 1;
6191 if (bufSize >= 0 && bufSize < minBufSize)
6192 {
6193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6194 return false;
6195 }
6196
6197 switch (pname)
6198 {
6199 case GL_TEXTURE_WRAP_S:
6200 case GL_TEXTURE_WRAP_T:
6201 case GL_TEXTURE_WRAP_R:
6202 if (!ValidateTextureWrapModeValue(context, params, false))
6203 {
6204 return false;
6205 }
6206 break;
6207
6208 case GL_TEXTURE_MIN_FILTER:
6209 if (!ValidateTextureMinFilterValue(context, params, false))
6210 {
6211 return false;
6212 }
6213 break;
6214
6215 case GL_TEXTURE_MAG_FILTER:
6216 if (!ValidateTextureMagFilterValue(context, params))
6217 {
6218 return false;
6219 }
6220 break;
6221
6222 case GL_TEXTURE_MIN_LOD:
6223 case GL_TEXTURE_MAX_LOD:
6224 // any value is permissible
6225 break;
6226
6227 case GL_TEXTURE_COMPARE_MODE:
6228 if (!ValidateTextureCompareModeValue(context, params))
6229 {
6230 return false;
6231 }
6232 break;
6233
6234 case GL_TEXTURE_COMPARE_FUNC:
6235 if (!ValidateTextureCompareFuncValue(context, params))
6236 {
6237 return false;
6238 }
6239 break;
6240
6241 case GL_TEXTURE_SRGB_DECODE_EXT:
6242 if (!ValidateTextureSRGBDecodeValue(context, params))
6243 {
6244 return false;
6245 }
6246 break;
6247
Luc Ferron1b1a8642018-01-23 15:12:01 -05006248 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6249 {
6250 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6251 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6252 {
6253 return false;
6254 }
6255 }
6256 break;
6257
Jamie Madill9696d072017-08-26 23:19:57 -04006258 default:
6259 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6260 return false;
6261 }
6262
6263 return true;
6264}
6265
6266template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6267template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6268
6269bool ValidateGetSamplerParameterBase(Context *context,
6270 GLuint sampler,
6271 GLenum pname,
6272 GLsizei *length)
6273{
6274 if (length)
6275 {
6276 *length = 0;
6277 }
6278
6279 if (context->getClientMajorVersion() < 3)
6280 {
6281 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6282 return false;
6283 }
6284
6285 if (!context->isSampler(sampler))
6286 {
6287 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6288 return false;
6289 }
6290
6291 switch (pname)
6292 {
6293 case GL_TEXTURE_WRAP_S:
6294 case GL_TEXTURE_WRAP_T:
6295 case GL_TEXTURE_WRAP_R:
6296 case GL_TEXTURE_MIN_FILTER:
6297 case GL_TEXTURE_MAG_FILTER:
6298 case GL_TEXTURE_MIN_LOD:
6299 case GL_TEXTURE_MAX_LOD:
6300 case GL_TEXTURE_COMPARE_MODE:
6301 case GL_TEXTURE_COMPARE_FUNC:
6302 break;
6303
Luc Ferron1b1a8642018-01-23 15:12:01 -05006304 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6305 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6306 {
6307 return false;
6308 }
6309 break;
6310
Jamie Madill9696d072017-08-26 23:19:57 -04006311 case GL_TEXTURE_SRGB_DECODE_EXT:
6312 if (!context->getExtensions().textureSRGBDecode)
6313 {
6314 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6315 return false;
6316 }
6317 break;
6318
6319 default:
6320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6321 return false;
6322 }
6323
6324 if (length)
6325 {
6326 *length = 1;
6327 }
6328 return true;
6329}
6330
6331bool ValidateGetInternalFormativBase(Context *context,
6332 GLenum target,
6333 GLenum internalformat,
6334 GLenum pname,
6335 GLsizei bufSize,
6336 GLsizei *numParams)
6337{
6338 if (numParams)
6339 {
6340 *numParams = 0;
6341 }
6342
6343 if (context->getClientMajorVersion() < 3)
6344 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006345 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006346 return false;
6347 }
6348
6349 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006350 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006351 {
6352 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6353 return false;
6354 }
6355
6356 switch (target)
6357 {
6358 case GL_RENDERBUFFER:
6359 break;
6360
6361 case GL_TEXTURE_2D_MULTISAMPLE:
6362 if (context->getClientVersion() < ES_3_1)
6363 {
6364 context->handleError(InvalidOperation()
6365 << "Texture target requires at least OpenGL ES 3.1.");
6366 return false;
6367 }
6368 break;
6369
6370 default:
6371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6372 return false;
6373 }
6374
6375 if (bufSize < 0)
6376 {
6377 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6378 return false;
6379 }
6380
6381 GLsizei maxWriteParams = 0;
6382 switch (pname)
6383 {
6384 case GL_NUM_SAMPLE_COUNTS:
6385 maxWriteParams = 1;
6386 break;
6387
6388 case GL_SAMPLES:
6389 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6390 break;
6391
6392 default:
6393 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6394 return false;
6395 }
6396
6397 if (numParams)
6398 {
6399 // glGetInternalFormativ will not overflow bufSize
6400 *numParams = std::min(bufSize, maxWriteParams);
6401 }
6402
6403 return true;
6404}
6405
Jamie Madille98b1b52018-03-08 09:47:23 -05006406bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6407{
Jamie Madill427064d2018-04-13 16:20:34 -04006408 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006409 {
6410 context->handleError(InvalidOperation());
6411 return false;
6412 }
6413 return true;
6414}
6415
Lingfeng Yang038dd532018-03-29 17:31:52 -07006416bool ValidateMultitextureUnit(Context *context, GLenum texture)
6417{
6418 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6419 {
6420 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6421 return false;
6422 }
6423 return true;
6424}
6425
Jamie Madillc29968b2016-01-20 11:17:23 -05006426} // namespace gl