blob: f8d213b2971e1618b254416f13e31eb4aed29cf6 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040025#include "libANGLE/validationES2.h"
26#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28#include "common/mathutil.h"
29#include "common/utilities.h"
30
Jamie Madille2e406c2016-06-02 13:04:10 -040031using namespace angle;
32
Geoff Lange8ebe7f2013-08-05 15:03:13 -040033namespace gl
34{
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050037bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
38{
39 // List of compressed format that require that the texture size is smaller than or a multiple of
40 // the compressed block size.
41 switch (internalFormat)
42 {
43 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
44 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
46 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
47 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
51 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
52 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
53 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
57 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 return true;
jchen10a99ed552017-09-22 08:10:32 +080059
Luc Ferron9dbaeba2018-02-01 07:26:59 -050060 default:
61 return false;
62 }
63}
64bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
65{
66 // Compressed sub textures have additional formats that requires exact size.
67 // ES 3.1, Section 8.7, Page 171
68 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
69 IsETC2EACFormat(internalFormat);
70}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030071
72bool DifferenceCanOverflow(GLint a, GLint b)
73{
74 CheckedNumeric<GLint> checkedA(a);
75 checkedA -= b;
76 // Use negation to make sure that the difference can't overflow regardless of the order.
77 checkedA = -checkedA;
78 return !checkedA.IsValid();
79}
80
Jamie Madill5b772312018-03-08 20:28:32 -050081bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040082{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070083 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040084 const gl::Program *program = state.getProgram();
85
Corentin Wallez327411e2016-12-09 11:09:17 -050086 bool webglCompatibility = context->getExtensions().webglCompatibility;
87
Jamie Madill51af38b2018-04-15 08:50:56 -040088 const VertexArray *vao = state.getVertexArray();
89 const AttributesMask &clientAttribs = vao->getEnabledClientMemoryAttribsMask();
90
91 if (clientAttribs.any())
92 {
93 if (webglCompatibility || !state.areClientArraysEnabled())
94 {
95 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
96 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
97 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
98 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
99 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
100 return false;
101 }
102 else if (vao->hasEnabledNullPointerClientArray())
103 {
104 // This is an application error that would normally result in a crash, but we catch it
105 // and return an error
106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
107 return false;
108 }
109 }
110
111 // If we're drawing zero vertices, we have enough data.
112 if (vertexCount <= 0 || primcount <= 0)
113 {
114 return true;
115 }
116
Jamie Madill231c7f52017-04-26 13:45:37 -0400117 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800118 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill51af38b2018-04-15 08:50:56 -0400119
Lingfeng Yang461b09a2018-04-23 09:02:09 -0700120 bool isGLES1 = context->getClientVersion() < Version(2, 0);
121
122 const AttributesMask &activeAttribs = ((isGLES1 ? context->getVertexArraysAttributeMask()
123 : program->getActiveAttribLocationsMask()) &
Jamie Madill02c9c042018-04-17 13:43:48 -0400124 vao->getEnabledAttributesMask() & ~clientAttribs);
Jamie Madill51af38b2018-04-15 08:50:56 -0400125
126 for (size_t attributeIndex : activeAttribs)
Jamie Madill1ca74672015-07-21 15:14:11 -0400127 {
128 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400129 ASSERT(attrib.enabled);
Corentin Wallez672f7f32017-06-15 17:42:17 -0400130
Lingfeng Yang038dd532018-03-29 17:31:52 -0700131 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Lingfeng Yang461b09a2018-04-23 09:02:09 -0700132 ASSERT(isGLES1 || program->isAttribLocationActive(attributeIndex));
Corentin Wallezfd456442016-12-21 17:57:00 -0500133
Jamie Madill02c9c042018-04-17 13:43:48 -0400134 GLint maxVertexElement = maxVertex;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300135 GLuint divisor = binding.getDivisor();
Jamie Madill02c9c042018-04-17 13:43:48 -0400136 if (divisor != 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500137 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300138 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500139 }
140
141 // We do manual overflow checks here instead of using safe_math.h because it was
142 // a bottleneck. Thanks to some properties of GL we know inequalities that can
143 // help us make the overflow checks faster.
144
145 // The max possible attribSize is 16 for a vector of 4 32 bit values.
146 constexpr uint64_t kMaxAttribSize = 16;
147 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
148 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
149
150 // We know attribStride is given as a GLsizei which is typedefed to int.
151 // We also know an upper bound for attribSize.
Jamie Madill02c9c042018-04-17 13:43:48 -0400152 static_assert(std::is_same<int, GLsizei>::value, "Unexpected type");
153 ASSERT(ComputeVertexAttributeStride(attrib, binding) == binding.getStride());
154 uint64_t attribStride = binding.getStride();
155 ASSERT(attribStride <= kIntMax && ComputeVertexAttributeTypeSize(attrib) <= kMaxAttribSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500156
Jamie Madill02c9c042018-04-17 13:43:48 -0400157 // Computing the product of two 32-bit ints will fit in 64 bits without overflow.
158 static_assert(kIntMax * kIntMax < kUint64Max, "Unexpected overflow");
159 uint64_t attribDataSizeMinusAttribSize = maxVertexElement * attribStride;
Corentin Wallezfd456442016-12-21 17:57:00 -0500160
161 // An overflow can happen when adding the offset, check for it.
Jamie Madill02c9c042018-04-17 13:43:48 -0400162 if (attribDataSizeMinusAttribSize > kUint64Max - attrib.cachedSizePlusRelativeOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500163 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700164 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500165 return false;
166 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500167
168 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
Jamie Madill02c9c042018-04-17 13:43:48 -0400169 // We can return INVALID_OPERATION if our array buffer does not have enough backing data.
170 if (attribDataSizeMinusAttribSize + attrib.cachedSizePlusRelativeOffset >
171 binding.getCachedBufferSizeMinusOffset())
Corentin Wallezfd456442016-12-21 17:57:00 -0500172 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500174 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400175 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400176 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800177
Jamie Madill7267aa62018-04-17 15:28:21 -0400178 if (webglCompatibility && vao->hasTransformFeedbackBindingConflict(activeAttribs))
Jamie Madill02c9c042018-04-17 13:43:48 -0400179 {
Jamie Madill7267aa62018-04-17 15:28:21 -0400180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexBufferBoundForTransformFeedback);
181 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400182 }
183
184 return true;
185}
186
Jamie Madill5b772312018-03-08 20:28:32 -0500187bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400188{
189 switch (type)
190 {
191 // Types referenced in Table 3.4 of the ES 2.0.25 spec
192 case GL_UNSIGNED_BYTE:
193 case GL_UNSIGNED_SHORT_4_4_4_4:
194 case GL_UNSIGNED_SHORT_5_5_5_1:
195 case GL_UNSIGNED_SHORT_5_6_5:
196 return context->getClientVersion() >= ES_2_0;
197
198 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
199 case GL_BYTE:
200 case GL_INT:
201 case GL_SHORT:
202 case GL_UNSIGNED_INT:
203 case GL_UNSIGNED_INT_10F_11F_11F_REV:
204 case GL_UNSIGNED_INT_24_8:
205 case GL_UNSIGNED_INT_2_10_10_10_REV:
206 case GL_UNSIGNED_INT_5_9_9_9_REV:
207 case GL_UNSIGNED_SHORT:
208 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
209 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
210 return context->getClientVersion() >= ES_3_0;
211
212 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400213 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
214 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400215
216 case GL_HALF_FLOAT:
217 return context->getClientVersion() >= ES_3_0 ||
218 context->getExtensions().textureHalfFloat;
219
220 case GL_HALF_FLOAT_OES:
221 return context->getExtensions().colorBufferHalfFloat;
222
223 default:
224 return false;
225 }
226}
227
Jamie Madill5b772312018-03-08 20:28:32 -0500228bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400229{
230 switch (format)
231 {
232 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
233 case GL_RGBA:
234 case GL_RGB:
235 case GL_ALPHA:
236 return context->getClientVersion() >= ES_2_0;
237
238 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
239 case GL_RG:
240 case GL_RED:
241 case GL_RGBA_INTEGER:
242 case GL_RGB_INTEGER:
243 case GL_RG_INTEGER:
244 case GL_RED_INTEGER:
245 return context->getClientVersion() >= ES_3_0;
246
247 case GL_SRGB_ALPHA_EXT:
248 case GL_SRGB_EXT:
249 return context->getExtensions().sRGB;
250
251 case GL_BGRA_EXT:
252 return context->getExtensions().readFormatBGRA;
253
254 default:
255 return false;
256 }
257}
258
Jamie Madill5b772312018-03-08 20:28:32 -0500259bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400260 GLenum framebufferComponentType,
261 GLenum format,
262 GLenum type)
263{
264 switch (framebufferComponentType)
265 {
266 case GL_UNSIGNED_NORMALIZED:
267 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
268 // ReadPixels with BGRA even if the extension is not present
269 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
270 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
271 type == GL_UNSIGNED_BYTE);
272
273 case GL_SIGNED_NORMALIZED:
274 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
275
276 case GL_INT:
277 return (format == GL_RGBA_INTEGER && type == GL_INT);
278
279 case GL_UNSIGNED_INT:
280 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
281
282 case GL_FLOAT:
283 return (format == GL_RGBA && type == GL_FLOAT);
284
285 default:
286 UNREACHABLE();
287 return false;
288 }
289}
290
Geoff Langc1984ed2016-10-07 12:41:00 -0400291template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400292bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400293{
294 switch (ConvertToGLenum(params[0]))
295 {
296 case GL_CLAMP_TO_EDGE:
297 break;
298
299 case GL_REPEAT:
300 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400301 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400302 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400303 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700304 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 return false;
306 }
307 break;
308
309 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700310 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400311 return false;
312 }
313
314 return true;
315}
316
317template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400318bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400319{
320 switch (ConvertToGLenum(params[0]))
321 {
322 case GL_NEAREST:
323 case GL_LINEAR:
324 break;
325
326 case GL_NEAREST_MIPMAP_NEAREST:
327 case GL_LINEAR_MIPMAP_NEAREST:
328 case GL_NEAREST_MIPMAP_LINEAR:
329 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400330 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400331 {
332 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700333 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400334 return false;
335 }
336 break;
337
338 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400340 return false;
341 }
342
343 return true;
344}
345
346template <typename ParamType>
347bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
348{
349 switch (ConvertToGLenum(params[0]))
350 {
351 case GL_NEAREST:
352 case GL_LINEAR:
353 break;
354
355 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700356 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400357 return false;
358 }
359
360 return true;
361}
362
363template <typename ParamType>
364bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
365{
366 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
367 switch (ConvertToGLenum(params[0]))
368 {
369 case GL_NONE:
370 case GL_COMPARE_REF_TO_TEXTURE:
371 break;
372
373 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400375 return false;
376 }
377
378 return true;
379}
380
381template <typename ParamType>
382bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
383{
384 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
385 switch (ConvertToGLenum(params[0]))
386 {
387 case GL_LEQUAL:
388 case GL_GEQUAL:
389 case GL_LESS:
390 case GL_GREATER:
391 case GL_EQUAL:
392 case GL_NOTEQUAL:
393 case GL_ALWAYS:
394 case GL_NEVER:
395 break;
396
397 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400399 return false;
400 }
401
402 return true;
403}
404
405template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700406bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
407{
408 if (!context->getExtensions().textureSRGBDecode)
409 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700410 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700411 return false;
412 }
413
414 switch (ConvertToGLenum(params[0]))
415 {
416 case GL_DECODE_EXT:
417 case GL_SKIP_DECODE_EXT:
418 break;
419
420 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700422 return false;
423 }
424
425 return true;
426}
427
Luc Ferron1b1a8642018-01-23 15:12:01 -0500428bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
429{
430 if (!context->getExtensions().textureFilterAnisotropic)
431 {
432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
433 return false;
434 }
435
436 return true;
437}
438
439bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
440{
441 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
442 {
443 return false;
444 }
445
446 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
447
448 if (paramValue < 1 || paramValue > largest)
449 {
450 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
451 return false;
452 }
453
454 return true;
455}
456
Jamie Madill5b772312018-03-08 20:28:32 -0500457bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400458{
459 const Program *program = context->getGLState().getProgram();
460 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
461
Brandon Jonesc405ae72017-12-06 14:15:03 -0800462 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
463 framebuffer->getDrawBufferTypeMask().to_ulong(),
464 program->getActiveOutputVariables().to_ulong(),
465 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400466 {
Brandon Jones76746f92017-11-22 11:44:41 -0800467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
468 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400469 }
470
471 return true;
472}
473
Jamie Madill5b772312018-03-08 20:28:32 -0500474bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400475{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700476 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400477 const Program *program = context->getGLState().getProgram();
478 const VertexArray *vao = context->getGLState().getVertexArray();
479
Brandon Jonesc405ae72017-12-06 14:15:03 -0800480 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
481 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
482 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
483
484 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
485 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
486 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
487
488 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
489 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400490 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800491 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
492 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400493 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400494 return true;
495}
496
Jiawei Shaofccebff2018-03-08 13:51:02 +0800497bool IsCompatibleDrawModeWithGeometryShader(GLenum drawMode,
498 GLenum geometryShaderInputPrimitiveType)
499{
500 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
501 switch (geometryShaderInputPrimitiveType)
502 {
503 case GL_POINTS:
504 return drawMode == GL_POINTS;
505 case GL_LINES:
506 return drawMode == GL_LINES || drawMode == GL_LINE_STRIP || drawMode == GL_LINE_LOOP;
507 case GL_LINES_ADJACENCY_EXT:
508 return drawMode == GL_LINES_ADJACENCY_EXT || drawMode == GL_LINE_STRIP_ADJACENCY_EXT;
509 case GL_TRIANGLES:
510 return drawMode == GL_TRIANGLES || drawMode == GL_TRIANGLE_FAN ||
511 drawMode == GL_TRIANGLE_STRIP;
512 case GL_TRIANGLES_ADJACENCY_EXT:
513 return drawMode == GL_TRIANGLES_ADJACENCY_EXT ||
514 drawMode == GL_TRIANGLE_STRIP_ADJACENCY_EXT;
515 default:
516 UNREACHABLE();
517 return false;
518 }
519}
520
Geoff Langf41a7152016-09-19 15:11:17 -0400521} // anonymous namespace
522
Brandon Jonesd1049182018-03-28 10:02:20 -0700523void SetRobustLengthParam(GLsizei *length, GLsizei value)
524{
525 if (length)
526 {
527 *length = value;
528 }
529}
530
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500531bool IsETC2EACFormat(const GLenum format)
532{
533 // ES 3.1, Table 8.19
534 switch (format)
535 {
536 case GL_COMPRESSED_R11_EAC:
537 case GL_COMPRESSED_SIGNED_R11_EAC:
538 case GL_COMPRESSED_RG11_EAC:
539 case GL_COMPRESSED_SIGNED_RG11_EAC:
540 case GL_COMPRESSED_RGB8_ETC2:
541 case GL_COMPRESSED_SRGB8_ETC2:
542 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
543 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
544 case GL_COMPRESSED_RGBA8_ETC2_EAC:
545 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
546 return true;
547
548 default:
549 return false;
550 }
551}
552
Jamie Madill5b772312018-03-08 20:28:32 -0500553bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400554{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800555 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400556 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800557 case TextureType::_2D:
558 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800559 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400560
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800561 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400562 return context->getExtensions().textureRectangle;
563
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800564 case TextureType::_3D:
565 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800566 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500567
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800568 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800569 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400570
He Yunchaoced53ae2016-11-29 15:00:51 +0800571 default:
572 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500573 }
Jamie Madill35d15012013-10-07 10:46:37 -0400574}
575
Jamie Madill5b772312018-03-08 20:28:32 -0500576bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500577{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800578 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500579 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800580 case TextureType::_2D:
581 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500582 return true;
583
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800584 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400585 return context->getExtensions().textureRectangle;
586
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500587 default:
588 return false;
589 }
590}
591
Jamie Madill5b772312018-03-08 20:28:32 -0500592bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500593{
594 switch (target)
595 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800596 case TextureType::_3D:
597 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300598 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500599
600 default:
601 return false;
602 }
603}
604
Ian Ewellbda75592016-04-18 17:25:54 -0400605// Most texture GL calls are not compatible with external textures, so we have a separate validation
606// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500607bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400608{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800609 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400610 (context->getExtensions().eglImageExternal ||
611 context->getExtensions().eglStreamConsumerExternal);
612}
613
Shannon Woods4dfed832014-03-17 20:03:39 -0400614// This function differs from ValidTextureTarget in that the target must be
615// usable as the destination of a 2D operation-- so a cube face is valid, but
616// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400617// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500618bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400619{
620 switch (target)
621 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800622 case TextureTarget::_2D:
623 case TextureTarget::CubeMapNegativeX:
624 case TextureTarget::CubeMapNegativeY:
625 case TextureTarget::CubeMapNegativeZ:
626 case TextureTarget::CubeMapPositiveX:
627 case TextureTarget::CubeMapPositiveY:
628 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800629 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800630 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400631 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800632 default:
633 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500634 }
635}
636
Jamie Madill5b772312018-03-08 20:28:32 -0500637bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -0400638 GLenum mode,
639 GLsizei count,
640 GLenum type,
641 const GLvoid *indices,
642 GLsizei primcount)
643{
644 if (primcount < 0)
645 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700646 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400647 return false;
648 }
649
650 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
651 {
652 return false;
653 }
654
Jamie Madill9fdaa492018-02-16 10:52:11 -0500655 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400656}
657
658bool ValidateDrawArraysInstancedBase(Context *context,
659 GLenum mode,
660 GLint first,
661 GLsizei count,
662 GLsizei primcount)
663{
664 if (primcount < 0)
665 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700666 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400667 return false;
668 }
669
670 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
671 {
672 return false;
673 }
674
Jamie Madill9fdaa492018-02-16 10:52:11 -0500675 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400676}
677
Jamie Madill5b772312018-03-08 20:28:32 -0500678bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400679{
680 // Verify there is at least one active attribute with a divisor of zero
681 const State &state = context->getGLState();
682
683 Program *program = state.getProgram();
684
685 const auto &attribs = state.getVertexArray()->getVertexAttributes();
686 const auto &bindings = state.getVertexArray()->getVertexBindings();
687 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
688 {
689 const VertexAttribute &attrib = attribs[attributeIndex];
690 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300691 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400692 {
693 return true;
694 }
695 }
696
Brandon Jonesafa75152017-07-21 13:11:29 -0700697 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400698 return false;
699}
700
Jamie Madill5b772312018-03-08 20:28:32 -0500701bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500702{
703 switch (target)
704 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800705 case TextureType::_3D:
706 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800707 return true;
708 default:
709 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400710 }
711}
712
Jamie Madill5b772312018-03-08 20:28:32 -0500713bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800714{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800715 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800716 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800717 case TextureType::_2D:
718 case TextureType::_2DArray:
719 case TextureType::_2DMultisample:
720 case TextureType::CubeMap:
721 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800722 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800723 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400724 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800725 default:
726 return false;
727 }
728}
729
Jamie Madill5b772312018-03-08 20:28:32 -0500730bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500731{
He Yunchaoced53ae2016-11-29 15:00:51 +0800732 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
733 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400734 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500735
736 switch (target)
737 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800738 case GL_FRAMEBUFFER:
739 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400740
He Yunchaoced53ae2016-11-29 15:00:51 +0800741 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800742 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400743 return (context->getExtensions().framebufferBlit ||
744 context->getClientMajorVersion() >= 3);
745
He Yunchaoced53ae2016-11-29 15:00:51 +0800746 default:
747 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500748 }
749}
750
Jamie Madill5b772312018-03-08 20:28:32 -0500751bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400752{
Jamie Madillc29968b2016-01-20 11:17:23 -0500753 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400754 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800755 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400756 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800757 case TextureType::_2D:
758 case TextureType::_2DArray:
759 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500760 maxDimension = caps.max2DTextureSize;
761 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800762 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800763 maxDimension = caps.maxCubeMapTextureSize;
764 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800765 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400766 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800767 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800768 maxDimension = caps.max3DTextureSize;
769 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800770 default:
771 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400772 }
773
Brandon Jones6cad5662017-06-14 13:25:13 -0700774 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400775}
776
Jamie Madill5b772312018-03-08 20:28:32 -0500777bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800778 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700779 GLint level,
780 GLsizei width,
781 GLsizei height,
782 GLsizei depth,
783 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400784{
Brandon Jones6cad5662017-06-14 13:25:13 -0700785 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400786 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700787 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400788 return false;
789 }
Austin Kinross08528e12015-10-07 16:24:40 -0700790 // TexSubImage parameters can be NPOT without textureNPOT extension,
791 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500792 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500793 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500794 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400795 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400796 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700797 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400798 return false;
799 }
800
801 if (!ValidMipLevel(context, target, level))
802 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700803 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400804 return false;
805 }
806
807 return true;
808}
809
Geoff Lang966c9402017-04-18 12:38:27 -0400810bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
811{
812 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
813 (size % blockSize == 0);
814}
815
Jamie Madill5b772312018-03-08 20:28:32 -0500816bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500817 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400818 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500819 GLsizei width,
820 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400821{
Geoff Langca271392017-04-05 12:30:00 -0400822 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400823 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400824 {
825 return false;
826 }
827
Geoff Lang966c9402017-04-18 12:38:27 -0400828 if (width < 0 || height < 0)
829 {
830 return false;
831 }
832
833 if (CompressedTextureFormatRequiresExactSize(internalFormat))
834 {
835 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
836 // block size for level 0 but WebGL disallows this.
837 bool smallerThanBlockSizeAllowed =
838 level > 0 || !context->getExtensions().webglCompatibility;
839
840 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
841 smallerThanBlockSizeAllowed) ||
842 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
843 smallerThanBlockSizeAllowed))
844 {
845 return false;
846 }
847 }
848
849 return true;
850}
851
Jamie Madill5b772312018-03-08 20:28:32 -0500852bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400853 GLenum internalFormat,
854 GLint xoffset,
855 GLint yoffset,
856 GLsizei width,
857 GLsizei height,
858 size_t textureWidth,
859 size_t textureHeight)
860{
861 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
862 if (!formatInfo.compressed)
863 {
864 return false;
865 }
866
Geoff Lang44ff5a72017-02-03 15:15:43 -0500867 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400868 {
869 return false;
870 }
871
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500872 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400873 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500874 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400875 yoffset % formatInfo.compressedBlockHeight != 0)
876 {
877 return false;
878 }
879
880 // Allowed to either have data that is a multiple of block size or is smaller than the block
881 // size but fills the entire mip
882 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
883 static_cast<size_t>(width) == textureWidth &&
884 static_cast<size_t>(height) == textureHeight;
885 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
886 (height % formatInfo.compressedBlockHeight) == 0;
887 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400888 {
889 return false;
890 }
891 }
892
Geoff Langd4f180b2013-09-24 13:57:44 -0400893 return true;
894}
895
Jamie Madill5b772312018-03-08 20:28:32 -0500896bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800897 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400898 GLsizei width,
899 GLsizei height,
900 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400901 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400902 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400903 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400904 GLsizei imageSize)
905{
Corentin Wallez336129f2017-10-17 15:55:40 -0400906 gl::Buffer *pixelUnpackBuffer =
907 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400908 if (pixelUnpackBuffer == nullptr && imageSize < 0)
909 {
910 // Checks are not required
911 return true;
912 }
913
914 // ...the data would be unpacked from the buffer object such that the memory reads required
915 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400916 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
917 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400918 const gl::Extents size(width, height, depth);
919 const auto &unpack = context->getGLState().getUnpackState();
920
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800921 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400922 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
923 if (endByteOrErr.isError())
924 {
925 context->handleError(endByteOrErr.getError());
926 return false;
927 }
928
929 GLuint endByte = endByteOrErr.getResult();
930
931 if (pixelUnpackBuffer)
932 {
933 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
934 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
935 checkedEndByte += checkedOffset;
936
937 if (!checkedEndByte.IsValid() ||
938 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
939 {
940 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500941 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400942 return false;
943 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800944 if (context->getExtensions().webglCompatibility &&
945 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
946 {
947 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
948 PixelUnpackBufferBoundForTransformFeedback);
949 return false;
950 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400951 }
952 else
953 {
954 ASSERT(imageSize >= 0);
955 if (pixels == nullptr && imageSize != 0)
956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500957 context->handleError(InvalidOperation()
958 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400959 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400960 }
961
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400962 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500964 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400965 return false;
966 }
967 }
968
969 return true;
970}
971
Corentin Wallezad3ae902018-03-09 13:40:42 -0500972bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500973{
Geoff Lang37dde692014-01-31 16:34:54 -0500974 switch (queryType)
975 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500976 case QueryType::AnySamples:
977 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400978 return context->getClientMajorVersion() >= 3 ||
979 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500980 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800981 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500982 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800983 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500984 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500986 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800987 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800988 default:
989 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500990 }
991}
992
Jamie Madill5b772312018-03-08 20:28:32 -0500993bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400994 GLenum type,
995 GLboolean normalized,
996 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400997 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400998 bool pureInteger)
999{
1000 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001001 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1002 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1003 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1004 // parameter exceeds 255.
1005 constexpr GLsizei kMaxWebGLStride = 255;
1006 if (stride > kMaxWebGLStride)
1007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001008 context->handleError(InvalidValue()
1009 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001010 return false;
1011 }
1012
1013 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1014 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1015 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1016 // or an INVALID_OPERATION error is generated.
1017 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1018 size_t typeSize = GetVertexFormatTypeSize(internalType);
1019
1020 ASSERT(isPow2(typeSize) && typeSize > 0);
1021 size_t sizeMask = (typeSize - 1);
1022 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001024 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001025 return false;
1026 }
1027
1028 if ((stride & sizeMask) != 0)
1029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001031 return false;
1032 }
1033
1034 return true;
1035}
1036
Jamie Madill5b772312018-03-08 20:28:32 -05001037Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001038{
He Yunchaoced53ae2016-11-29 15:00:51 +08001039 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1040 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1041 // or program object and INVALID_OPERATION if the provided name identifies an object
1042 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001043
Dian Xiang769769a2015-09-09 15:20:08 -07001044 Program *validProgram = context->getProgram(id);
1045
1046 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001047 {
Dian Xiang769769a2015-09-09 15:20:08 -07001048 if (context->getShader(id))
1049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001051 }
1052 else
1053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001054 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001055 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001056 }
Dian Xiang769769a2015-09-09 15:20:08 -07001057
1058 return validProgram;
1059}
1060
Jamie Madill5b772312018-03-08 20:28:32 -05001061Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001062{
1063 // See ValidProgram for spec details.
1064
1065 Shader *validShader = context->getShader(id);
1066
1067 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001068 {
Dian Xiang769769a2015-09-09 15:20:08 -07001069 if (context->getProgram(id))
1070 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001072 }
1073 else
1074 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001075 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001076 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001077 }
Dian Xiang769769a2015-09-09 15:20:08 -07001078
1079 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001080}
1081
Geoff Langb1196682014-07-23 13:47:29 -04001082bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001083{
Geoff Langfa125c92017-10-24 13:01:46 -04001084 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001085 {
Geoff Langfa125c92017-10-24 13:01:46 -04001086 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1087 {
1088 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1089 return false;
1090 }
Jamie Madillb4472272014-07-03 10:38:55 -04001091
Geoff Langfa125c92017-10-24 13:01:46 -04001092 // Color attachment 0 is validated below because it is always valid
1093 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001094 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001095 {
Geoff Langfa125c92017-10-24 13:01:46 -04001096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001097 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001098 }
1099 }
1100 else
1101 {
1102 switch (attachment)
1103 {
Geoff Langfa125c92017-10-24 13:01:46 -04001104 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001105 case GL_DEPTH_ATTACHMENT:
1106 case GL_STENCIL_ATTACHMENT:
1107 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001108
He Yunchaoced53ae2016-11-29 15:00:51 +08001109 case GL_DEPTH_STENCIL_ATTACHMENT:
1110 if (!context->getExtensions().webglCompatibility &&
1111 context->getClientMajorVersion() < 3)
1112 {
Geoff Langfa125c92017-10-24 13:01:46 -04001113 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 return false;
1115 }
1116 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001117
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001121 }
1122 }
1123
1124 return true;
1125}
1126
Jamie Madill5b772312018-03-08 20:28:32 -05001127bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001128 GLenum target,
1129 GLsizei samples,
1130 GLenum internalformat,
1131 GLsizei width,
1132 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133{
1134 switch (target)
1135 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001136 case GL_RENDERBUFFER:
1137 break;
1138 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001140 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 }
1142
1143 if (width < 0 || height < 0 || samples < 0)
1144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001145 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001149 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1150 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1151
1152 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001153 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001155 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158
1159 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1160 // 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 -08001161 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001162 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1163 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001167 }
1168
Geoff Langaae65a42014-05-26 12:43:44 -04001169 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001175 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 if (handle == 0)
1177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001179 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001180 }
1181
1182 return true;
1183}
1184
He Yunchaoced53ae2016-11-29 15:00:51 +08001185bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1186 GLenum target,
1187 GLenum attachment,
1188 GLenum renderbuffertarget,
1189 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001190{
Geoff Lange8afa902017-09-27 15:00:43 -04001191 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001193 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001194 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001195 }
1196
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001197 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001198
Jamie Madill84115c92015-04-23 15:00:07 -04001199 ASSERT(framebuffer);
1200 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001203 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001204 }
1205
Jamie Madillb4472272014-07-03 10:38:55 -04001206 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207 {
Jamie Madillb4472272014-07-03 10:38:55 -04001208 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001209 }
1210
Jamie Madillab9d82c2014-01-21 16:38:14 -05001211 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1212 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1213 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1214 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1215 if (renderbuffer != 0)
1216 {
1217 if (!context->getRenderbuffer(renderbuffer))
1218 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001220 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001221 }
1222 }
1223
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001224 return true;
1225}
1226
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001227bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001228 GLint srcX0,
1229 GLint srcY0,
1230 GLint srcX1,
1231 GLint srcY1,
1232 GLint dstX0,
1233 GLint dstY0,
1234 GLint dstX1,
1235 GLint dstY1,
1236 GLbitfield mask,
1237 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001238{
1239 switch (filter)
1240 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001241 case GL_NEAREST:
1242 break;
1243 case GL_LINEAR:
1244 break;
1245 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001246 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001247 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001248 }
1249
1250 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001252 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 }
1255
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1257 // color buffer, leaving only nearest being unfiltered from above
1258 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001261 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 }
1263
Jamie Madill51f40ec2016-06-15 14:06:00 -04001264 const auto &glState = context->getGLState();
1265 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1266 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001267
1268 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001270 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001271 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001272 }
1273
Jamie Madill427064d2018-04-13 16:20:34 -04001274 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001275 {
Jamie Madill48faf802014-11-06 15:27:22 -05001276 return false;
1277 }
1278
Jamie Madill427064d2018-04-13 16:20:34 -04001279 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001280 {
Jamie Madill48faf802014-11-06 15:27:22 -05001281 return false;
1282 }
1283
Qin Jiajiaaef92162018-02-27 13:51:44 +08001284 if (readFramebuffer->id() == drawFramebuffer->id())
1285 {
1286 context->handleError(InvalidOperation());
1287 return false;
1288 }
1289
Jamie Madille98b1b52018-03-08 09:47:23 -05001290 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 {
Geoff Langb1196682014-07-23 13:47:29 -04001292 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 }
1294
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001295 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1296 // always run it in order to avoid triggering driver bugs.
1297 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1298 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001299 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001300 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1301 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001302 }
1303
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1305
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306 if (mask & GL_COLOR_BUFFER_BIT)
1307 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001308 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001309 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310
He Yunchao66a41a22016-12-15 16:45:05 +08001311 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001313 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314
Geoff Langa15472a2015-08-11 11:48:03 -04001315 for (size_t drawbufferIdx = 0;
1316 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001317 {
Geoff Langa15472a2015-08-11 11:48:03 -04001318 const FramebufferAttachment *attachment =
1319 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1320 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001321 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001322 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323
Geoff Langb2f3d052013-08-13 12:49:27 -04001324 // The GL ES 3.0.2 spec (pg 193) states that:
1325 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001326 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1327 // as well
1328 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1329 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001330 // Changes with EXT_color_buffer_float:
1331 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001332 GLenum readComponentType = readFormat.info->componentType;
1333 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001334 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001335 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001336 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001337 drawComponentType == GL_SIGNED_NORMALIZED);
1338
1339 if (extensions.colorBufferFloat)
1340 {
1341 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1342 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1343
1344 if (readFixedOrFloat != drawFixedOrFloat)
1345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001346 context->handleError(InvalidOperation()
1347 << "If the read buffer contains fixed-point or "
1348 "floating-point values, the draw buffer must "
1349 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001350 return false;
1351 }
1352 }
1353 else if (readFixedPoint != drawFixedPoint)
1354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001355 context->handleError(InvalidOperation()
1356 << "If the read buffer contains fixed-point values, "
1357 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001358 return false;
1359 }
1360
1361 if (readComponentType == GL_UNSIGNED_INT &&
1362 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 }
1367
Jamie Madill6163c752015-12-07 16:32:59 -05001368 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001371 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 }
1373
Jamie Madilla3944d42016-07-22 22:13:26 -04001374 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001375 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001378 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 }
Geoff Lange4915782017-04-12 15:19:07 -04001380
1381 if (context->getExtensions().webglCompatibility &&
1382 *readColorBuffer == *attachment)
1383 {
1384 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 InvalidOperation()
1386 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001387 return false;
1388 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
1390 }
1391
Jamie Madilla3944d42016-07-22 22:13:26 -04001392 if ((readFormat.info->componentType == GL_INT ||
1393 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1394 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001396 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 }
He Yunchao66a41a22016-12-15 16:45:05 +08001400 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1401 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1402 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1403 // situation is an application error that would lead to a crash in ANGLE.
1404 else if (drawFramebuffer->hasEnabledDrawBuffer())
1405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(
1407 InvalidOperation()
1408 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001409 return false;
1410 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
1412
He Yunchaoced53ae2016-11-29 15:00:51 +08001413 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001414 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1415 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001417 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001419 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001420 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001421 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001422 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001423
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001424 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 {
Kenneth Russell69382852017-07-21 16:38:44 -04001426 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001428 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001431
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001432 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001434 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001435 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 }
Geoff Lange4915782017-04-12 15:19:07 -04001437
1438 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001440 context->handleError(
1441 InvalidOperation()
1442 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001443 return false;
1444 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 }
He Yunchao66a41a22016-12-15 16:45:05 +08001446 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1447 else if (drawBuffer)
1448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001449 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1450 "depth/stencil attachment of a "
1451 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001452 return false;
1453 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
1455 }
1456
Martin Radeva3ed4572017-07-27 18:29:37 +03001457 // ANGLE_multiview, Revision 1:
1458 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1459 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1460 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1461 {
1462 context->handleError(InvalidFramebufferOperation()
1463 << "Attempt to read from a multi-view framebuffer.");
1464 return false;
1465 }
1466 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1467 {
1468 context->handleError(InvalidFramebufferOperation()
1469 << "Attempt to write to a multi-view framebuffer.");
1470 return false;
1471 }
1472
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 return true;
1474}
1475
Jamie Madill4928b7c2017-06-20 12:57:39 -04001476bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001477 GLint x,
1478 GLint y,
1479 GLsizei width,
1480 GLsizei height,
1481 GLenum format,
1482 GLenum type,
1483 GLsizei bufSize,
1484 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001485 GLsizei *columns,
1486 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001487 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001488{
1489 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001490 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001491 return false;
1492 }
1493
Brandon Jonesd1049182018-03-28 10:02:20 -07001494 GLsizei writeLength = 0;
1495 GLsizei writeColumns = 0;
1496 GLsizei writeRows = 0;
1497
1498 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1499 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001500 {
Geoff Langb1196682014-07-23 13:47:29 -04001501 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001502 }
1503
Brandon Jonesd1049182018-03-28 10:02:20 -07001504 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001505 {
Geoff Langb1196682014-07-23 13:47:29 -04001506 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001507 }
1508
Brandon Jonesd1049182018-03-28 10:02:20 -07001509 SetRobustLengthParam(length, writeLength);
1510 SetRobustLengthParam(columns, writeColumns);
1511 SetRobustLengthParam(rows, writeRows);
1512
Jamie Madillc29968b2016-01-20 11:17:23 -05001513 return true;
1514}
1515
1516bool ValidateReadnPixelsEXT(Context *context,
1517 GLint x,
1518 GLint y,
1519 GLsizei width,
1520 GLsizei height,
1521 GLenum format,
1522 GLenum type,
1523 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001524 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001525{
1526 if (bufSize < 0)
1527 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001528 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001529 return false;
1530 }
1531
Geoff Lang62fce5b2016-09-30 10:46:35 -04001532 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001533 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001534}
Jamie Madill26e91952014-03-05 15:01:27 -05001535
Jamie Madill4928b7c2017-06-20 12:57:39 -04001536bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001537 GLint x,
1538 GLint y,
1539 GLsizei width,
1540 GLsizei height,
1541 GLenum format,
1542 GLenum type,
1543 GLsizei bufSize,
1544 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001545 GLsizei *columns,
1546 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001547 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001548{
Brandon Jonesd1049182018-03-28 10:02:20 -07001549 GLsizei writeLength = 0;
1550 GLsizei writeColumns = 0;
1551 GLsizei writeRows = 0;
1552
Geoff Lang62fce5b2016-09-30 10:46:35 -04001553 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001554 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001555 return false;
1556 }
1557
Brandon Jonesd1049182018-03-28 10:02:20 -07001558 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1559 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001560 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001561 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001562 }
1563
Brandon Jonesd1049182018-03-28 10:02:20 -07001564 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001565 {
1566 return false;
1567 }
1568
Brandon Jonesd1049182018-03-28 10:02:20 -07001569 SetRobustLengthParam(length, writeLength);
1570 SetRobustLengthParam(columns, writeColumns);
1571 SetRobustLengthParam(rows, writeRows);
1572
Geoff Lang62fce5b2016-09-30 10:46:35 -04001573 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001574}
1575
Jamie Madillf0e04492017-08-26 15:28:42 -04001576bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001577{
1578 if (!context->getExtensions().occlusionQueryBoolean &&
1579 !context->getExtensions().disjointTimerQuery)
1580 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001582 return false;
1583 }
1584
Olli Etuaho41997e72016-03-10 13:38:39 +02001585 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001586}
1587
Jamie Madillf0e04492017-08-26 15:28:42 -04001588bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001589{
1590 if (!context->getExtensions().occlusionQueryBoolean &&
1591 !context->getExtensions().disjointTimerQuery)
1592 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001593 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001594 return false;
1595 }
1596
Olli Etuaho41997e72016-03-10 13:38:39 +02001597 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001598}
1599
Jamie Madillf0e04492017-08-26 15:28:42 -04001600bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1601{
1602 if (!context->getExtensions().occlusionQueryBoolean &&
1603 !context->getExtensions().disjointTimerQuery)
1604 {
1605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1606 return false;
1607 }
1608
1609 return true;
1610}
1611
Corentin Wallezad3ae902018-03-09 13:40:42 -05001612bool ValidateBeginQueryBase(gl::Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001613{
1614 if (!ValidQueryType(context, target))
1615 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001616 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001617 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001618 }
1619
1620 if (id == 0)
1621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001622 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001623 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001624 }
1625
1626 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1627 // of zero, if the active query object name for <target> is non-zero (for the
1628 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1629 // the active query for either target is non-zero), if <id> is the name of an
1630 // existing query object whose type does not match <target>, or if <id> is the
1631 // active query object name for any query type, the error INVALID_OPERATION is
1632 // generated.
1633
1634 // Ensure no other queries are active
1635 // NOTE: If other queries than occlusion are supported, we will need to check
1636 // separately that:
1637 // a) The query ID passed is not the current active query for any target/type
1638 // b) There are no active queries for the requested target (and in the case
1639 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1640 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001641
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001642 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001644 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001645 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001646 }
1647
1648 Query *queryObject = context->getQuery(id, true, target);
1649
1650 // check that name was obtained with glGenQueries
1651 if (!queryObject)
1652 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001654 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001655 }
1656
1657 // check for type mismatch
1658 if (queryObject->getType() != target)
1659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001660 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001661 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001662 }
1663
1664 return true;
1665}
1666
Corentin Wallezad3ae902018-03-09 13:40:42 -05001667bool ValidateBeginQueryEXT(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001668{
1669 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001670 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673 return false;
1674 }
1675
1676 return ValidateBeginQueryBase(context, target, id);
1677}
1678
Corentin Wallezad3ae902018-03-09 13:40:42 -05001679bool ValidateEndQueryBase(gl::Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001680{
1681 if (!ValidQueryType(context, target))
1682 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001683 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001684 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001685 }
1686
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001687 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001688
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001689 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001691 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001692 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001693 }
1694
Jamie Madill45c785d2014-05-13 14:09:34 -04001695 return true;
1696}
1697
Corentin Wallezad3ae902018-03-09 13:40:42 -05001698bool ValidateEndQueryEXT(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001699{
1700 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001701 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001703 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001704 return false;
1705 }
1706
1707 return ValidateEndQueryBase(context, target);
1708}
1709
Corentin Wallezad3ae902018-03-09 13:40:42 -05001710bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001711{
1712 if (!context->getExtensions().disjointTimerQuery)
1713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001714 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715 return false;
1716 }
1717
Corentin Wallezad3ae902018-03-09 13:40:42 -05001718 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001719 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 return false;
1722 }
1723
1724 Query *queryObject = context->getQuery(id, true, target);
1725 if (queryObject == nullptr)
1726 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001727 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001728 return false;
1729 }
1730
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001731 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001733 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001734 return false;
1735 }
1736
1737 return true;
1738}
1739
Corentin Wallezad3ae902018-03-09 13:40:42 -05001740bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001741{
Geoff Lang2186c382016-10-14 10:54:54 -04001742 if (numParams)
1743 {
1744 *numParams = 0;
1745 }
1746
Corentin Wallezad3ae902018-03-09 13:40:42 -05001747 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001749 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750 return false;
1751 }
1752
1753 switch (pname)
1754 {
1755 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001756 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001758 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759 return false;
1760 }
1761 break;
1762 case GL_QUERY_COUNTER_BITS_EXT:
1763 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001764 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001766 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767 return false;
1768 }
1769 break;
1770 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001772 return false;
1773 }
1774
Geoff Lang2186c382016-10-14 10:54:54 -04001775 if (numParams)
1776 {
1777 // All queries return only one value
1778 *numParams = 1;
1779 }
1780
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001781 return true;
1782}
1783
Corentin Wallezad3ae902018-03-09 13:40:42 -05001784bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001785{
1786 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001787 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001789 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001790 return false;
1791 }
1792
Geoff Lang2186c382016-10-14 10:54:54 -04001793 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001794}
1795
Geoff Lang2186c382016-10-14 10:54:54 -04001796bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001797 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001798 GLenum pname,
1799 GLsizei bufSize,
1800 GLsizei *length,
1801 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802{
Geoff Lang2186c382016-10-14 10:54:54 -04001803 if (!ValidateRobustEntryPoint(context, bufSize))
1804 {
1805 return false;
1806 }
1807
Brandon Jonesd1049182018-03-28 10:02:20 -07001808 GLsizei numParams = 0;
1809
1810 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001811 {
1812 return false;
1813 }
1814
Brandon Jonesd1049182018-03-28 10:02:20 -07001815 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001816 {
1817 return false;
1818 }
1819
Brandon Jonesd1049182018-03-28 10:02:20 -07001820 SetRobustLengthParam(length, numParams);
1821
Geoff Lang2186c382016-10-14 10:54:54 -04001822 return true;
1823}
1824
1825bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1826{
1827 if (numParams)
1828 {
1829 *numParams = 0;
1830 }
1831
Corentin Wallezad3ae902018-03-09 13:40:42 -05001832 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001833
1834 if (!queryObject)
1835 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001836 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001837 return false;
1838 }
1839
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001840 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001842 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001843 return false;
1844 }
1845
1846 switch (pname)
1847 {
1848 case GL_QUERY_RESULT_EXT:
1849 case GL_QUERY_RESULT_AVAILABLE_EXT:
1850 break;
1851
1852 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001853 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001854 return false;
1855 }
1856
Geoff Lang2186c382016-10-14 10:54:54 -04001857 if (numParams)
1858 {
1859 *numParams = 1;
1860 }
1861
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862 return true;
1863}
1864
1865bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1866{
1867 if (!context->getExtensions().disjointTimerQuery)
1868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001869 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001870 return false;
1871 }
Geoff Lang2186c382016-10-14 10:54:54 -04001872 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1873}
1874
1875bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1876 GLuint id,
1877 GLenum pname,
1878 GLsizei bufSize,
1879 GLsizei *length,
1880 GLint *params)
1881{
1882 if (!context->getExtensions().disjointTimerQuery)
1883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001884 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001885 return false;
1886 }
1887
1888 if (!ValidateRobustEntryPoint(context, bufSize))
1889 {
1890 return false;
1891 }
1892
Brandon Jonesd1049182018-03-28 10:02:20 -07001893 GLsizei numParams = 0;
1894
1895 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001896 {
1897 return false;
1898 }
1899
Brandon Jonesd1049182018-03-28 10:02:20 -07001900 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001901 {
1902 return false;
1903 }
1904
Brandon Jonesd1049182018-03-28 10:02:20 -07001905 SetRobustLengthParam(length, numParams);
1906
Geoff Lang2186c382016-10-14 10:54:54 -04001907 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001908}
1909
1910bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1911{
1912 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001913 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001915 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916 return false;
1917 }
Geoff Lang2186c382016-10-14 10:54:54 -04001918 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1919}
1920
1921bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1922 GLuint id,
1923 GLenum pname,
1924 GLsizei bufSize,
1925 GLsizei *length,
1926 GLuint *params)
1927{
1928 if (!context->getExtensions().disjointTimerQuery &&
1929 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001932 return false;
1933 }
1934
1935 if (!ValidateRobustEntryPoint(context, bufSize))
1936 {
1937 return false;
1938 }
1939
Brandon Jonesd1049182018-03-28 10:02:20 -07001940 GLsizei numParams = 0;
1941
1942 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001943 {
1944 return false;
1945 }
1946
Brandon Jonesd1049182018-03-28 10:02:20 -07001947 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001948 {
1949 return false;
1950 }
1951
Brandon Jonesd1049182018-03-28 10:02:20 -07001952 SetRobustLengthParam(length, numParams);
1953
Geoff Lang2186c382016-10-14 10:54:54 -04001954 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001955}
1956
1957bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1958{
1959 if (!context->getExtensions().disjointTimerQuery)
1960 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001961 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001962 return false;
1963 }
Geoff Lang2186c382016-10-14 10:54:54 -04001964 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1965}
1966
1967bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1968 GLuint id,
1969 GLenum pname,
1970 GLsizei bufSize,
1971 GLsizei *length,
1972 GLint64 *params)
1973{
1974 if (!context->getExtensions().disjointTimerQuery)
1975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001977 return false;
1978 }
1979
1980 if (!ValidateRobustEntryPoint(context, bufSize))
1981 {
1982 return false;
1983 }
1984
Brandon Jonesd1049182018-03-28 10:02:20 -07001985 GLsizei numParams = 0;
1986
1987 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001988 {
1989 return false;
1990 }
1991
Brandon Jonesd1049182018-03-28 10:02:20 -07001992 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001993 {
1994 return false;
1995 }
1996
Brandon Jonesd1049182018-03-28 10:02:20 -07001997 SetRobustLengthParam(length, numParams);
1998
Geoff Lang2186c382016-10-14 10:54:54 -04001999 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002000}
2001
2002bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2003{
2004 if (!context->getExtensions().disjointTimerQuery)
2005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002007 return false;
2008 }
Geoff Lang2186c382016-10-14 10:54:54 -04002009 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2010}
2011
2012bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2013 GLuint id,
2014 GLenum pname,
2015 GLsizei bufSize,
2016 GLsizei *length,
2017 GLuint64 *params)
2018{
2019 if (!context->getExtensions().disjointTimerQuery)
2020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002021 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002022 return false;
2023 }
2024
2025 if (!ValidateRobustEntryPoint(context, bufSize))
2026 {
2027 return false;
2028 }
2029
Brandon Jonesd1049182018-03-28 10:02:20 -07002030 GLsizei numParams = 0;
2031
2032 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002033 {
2034 return false;
2035 }
2036
Brandon Jonesd1049182018-03-28 10:02:20 -07002037 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002038 {
2039 return false;
2040 }
2041
Brandon Jonesd1049182018-03-28 10:02:20 -07002042 SetRobustLengthParam(length, numParams);
2043
Geoff Lang2186c382016-10-14 10:54:54 -04002044 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002045}
2046
Jamie Madill5b772312018-03-08 20:28:32 -05002047bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002048 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002049 GLint location,
2050 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002051 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002052{
Jiajia Qin5451d532017-11-16 17:16:34 +08002053 // TODO(Jiajia): Add image uniform check in future.
2054 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002055 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002056 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002057 return false;
2058 }
2059
Jiajia Qin5451d532017-11-16 17:16:34 +08002060 if (!program)
2061 {
2062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2063 return false;
2064 }
2065
2066 if (!program->isLinked())
2067 {
2068 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2069 return false;
2070 }
2071
2072 if (location == -1)
2073 {
2074 // Silently ignore the uniform command
2075 return false;
2076 }
2077
2078 const auto &uniformLocations = program->getUniformLocations();
2079 size_t castedLocation = static_cast<size_t>(location);
2080 if (castedLocation >= uniformLocations.size())
2081 {
2082 context->handleError(InvalidOperation() << "Invalid uniform location");
2083 return false;
2084 }
2085
2086 const auto &uniformLocation = uniformLocations[castedLocation];
2087 if (uniformLocation.ignored)
2088 {
2089 // Silently ignore the uniform command
2090 return false;
2091 }
2092
2093 if (!uniformLocation.used())
2094 {
2095 context->handleError(InvalidOperation());
2096 return false;
2097 }
2098
2099 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2100
2101 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002102 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002103 {
2104 context->handleError(InvalidOperation());
2105 return false;
2106 }
2107
2108 *uniformOut = &uniform;
2109 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002110}
2111
Jamie Madill5b772312018-03-08 20:28:32 -05002112bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002113 GLenum uniformType,
2114 GLsizei count,
2115 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002116{
Jiajia Qin5451d532017-11-16 17:16:34 +08002117 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2118 // It is compatible with INT or BOOL.
2119 // Do these cheap tests first, for a little extra speed.
2120 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002121 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002122 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002123 }
2124
Jiajia Qin5451d532017-11-16 17:16:34 +08002125 if (IsSamplerType(uniformType))
2126 {
2127 // Check that the values are in range.
2128 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2129 for (GLsizei i = 0; i < count; ++i)
2130 {
2131 if (value[i] < 0 || value[i] >= max)
2132 {
2133 context->handleError(InvalidValue() << "sampler uniform value out of range");
2134 return false;
2135 }
2136 }
2137 return true;
2138 }
2139
2140 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2141 return false;
2142}
2143
Jamie Madill5b772312018-03-08 20:28:32 -05002144bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002145{
2146 // Check that the value type is compatible with uniform type.
2147 // Do the cheaper test first, for a little extra speed.
2148 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2149 {
2150 return true;
2151 }
2152
2153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2154 return false;
2155}
2156
Jamie Madill5b772312018-03-08 20:28:32 -05002157bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002158{
2159 // Check that the value type is compatible with uniform type.
2160 if (valueType == uniformType)
2161 {
2162 return true;
2163 }
2164
2165 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2166 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002167}
2168
Jamie Madill5b772312018-03-08 20:28:32 -05002169bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002170{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002171 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002172 gl::Program *programObject = context->getGLState().getProgram();
2173 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2174 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002175}
2176
Jamie Madill5b772312018-03-08 20:28:32 -05002177bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002178{
2179 const LinkedUniform *uniform = nullptr;
2180 gl::Program *programObject = context->getGLState().getProgram();
2181 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2182 ValidateUniform1ivValue(context, uniform->type, count, value);
2183}
2184
Jamie Madill5b772312018-03-08 20:28:32 -05002185bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002186 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002187 GLint location,
2188 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002189 GLboolean transpose)
2190{
Geoff Lang92019432017-11-20 13:09:34 -05002191 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002193 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002194 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002195 }
2196
Jamie Madill62d31cb2015-09-11 13:25:51 -04002197 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002198 gl::Program *programObject = context->getGLState().getProgram();
2199 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2200 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002201}
2202
Jamie Madill5b772312018-03-08 20:28:32 -05002203bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002204{
2205 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002207 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002208 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002209 }
2210
Jamie Madill0af26e12015-03-05 19:54:33 -05002211 const Caps &caps = context->getCaps();
2212
Jamie Madill893ab082014-05-16 16:56:10 -04002213 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2214 {
2215 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2216
Jamie Madill0af26e12015-03-05 19:54:33 -05002217 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002219 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002220 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002221 }
2222 }
2223
2224 switch (pname)
2225 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002226 case GL_TEXTURE_BINDING_2D:
2227 case GL_TEXTURE_BINDING_CUBE_MAP:
2228 case GL_TEXTURE_BINDING_3D:
2229 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002230 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002231 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002232 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2233 if (!context->getExtensions().textureRectangle)
2234 {
2235 context->handleError(InvalidEnum()
2236 << "ANGLE_texture_rectangle extension not present");
2237 return false;
2238 }
2239 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002240 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2241 if (!context->getExtensions().eglStreamConsumerExternal &&
2242 !context->getExtensions().eglImageExternal)
2243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002244 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2245 "nor GL_OES_EGL_image_external "
2246 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002247 return false;
2248 }
2249 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002250
He Yunchaoced53ae2016-11-29 15:00:51 +08002251 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2252 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002253 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002254 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2255 ASSERT(readFramebuffer);
2256
Jamie Madill427064d2018-04-13 16:20:34 -04002257 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002258 {
Geoff Langb1196682014-07-23 13:47:29 -04002259 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002260 }
2261
Jamie Madille98b1b52018-03-08 09:47:23 -05002262 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002263 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002264 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002265 return false;
2266 }
2267
Jamie Madille98b1b52018-03-08 09:47:23 -05002268 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002269 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002271 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002272 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002273 }
2274 }
2275 break;
2276
He Yunchaoced53ae2016-11-29 15:00:51 +08002277 default:
2278 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002279 }
2280
2281 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002282 if (*numParams == 0)
2283 {
2284 return false;
2285 }
2286
2287 return true;
2288}
2289
Brandon Jonesd1049182018-03-28 10:02:20 -07002290bool ValidateGetBooleanvRobustANGLE(Context *context,
2291 GLenum pname,
2292 GLsizei bufSize,
2293 GLsizei *length,
2294 GLboolean *params)
2295{
2296 GLenum nativeType;
2297 unsigned int numParams = 0;
2298
2299 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2300 {
2301 return false;
2302 }
2303
2304 SetRobustLengthParam(length, numParams);
2305
2306 return true;
2307}
2308
2309bool ValidateGetFloatvRobustANGLE(Context *context,
2310 GLenum pname,
2311 GLsizei bufSize,
2312 GLsizei *length,
2313 GLfloat *params)
2314{
2315 GLenum nativeType;
2316 unsigned int numParams = 0;
2317
2318 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2319 {
2320 return false;
2321 }
2322
2323 SetRobustLengthParam(length, numParams);
2324
2325 return true;
2326}
2327
2328bool ValidateGetIntegervRobustANGLE(Context *context,
2329 GLenum pname,
2330 GLsizei bufSize,
2331 GLsizei *length,
2332 GLint *data)
2333{
2334 GLenum nativeType;
2335 unsigned int numParams = 0;
2336
2337 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2338 {
2339 return false;
2340 }
2341
2342 SetRobustLengthParam(length, numParams);
2343
2344 return true;
2345}
2346
2347bool ValidateGetInteger64vRobustANGLE(Context *context,
2348 GLenum pname,
2349 GLsizei bufSize,
2350 GLsizei *length,
2351 GLint64 *data)
2352{
2353 GLenum nativeType;
2354 unsigned int numParams = 0;
2355
2356 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2357 {
2358 return false;
2359 }
2360
2361 if (nativeType == GL_INT_64_ANGLEX)
2362 {
2363 CastStateValues(context, nativeType, pname, numParams, data);
2364 return false;
2365 }
2366
2367 SetRobustLengthParam(length, numParams);
2368 return true;
2369}
2370
Jamie Madill5b772312018-03-08 20:28:32 -05002371bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002372 GLenum pname,
2373 GLsizei bufSize,
2374 GLenum *nativeType,
2375 unsigned int *numParams)
2376{
2377 if (!ValidateRobustEntryPoint(context, bufSize))
2378 {
2379 return false;
2380 }
2381
2382 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2383 {
2384 return false;
2385 }
2386
2387 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002388 {
2389 return false;
2390 }
2391
2392 return true;
2393}
2394
Jamie Madill5b772312018-03-08 20:28:32 -05002395bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002396 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002397 GLint level,
2398 GLenum internalformat,
2399 bool isSubImage,
2400 GLint xoffset,
2401 GLint yoffset,
2402 GLint zoffset,
2403 GLint x,
2404 GLint y,
2405 GLsizei width,
2406 GLsizei height,
2407 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002408 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002409{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002410 TextureType texType = TextureTargetToType(target);
2411
Brandon Jones6cad5662017-06-14 13:25:13 -07002412 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002413 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002414 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2415 return false;
2416 }
2417
2418 if (width < 0 || height < 0)
2419 {
2420 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002421 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002422 }
2423
He Yunchaoced53ae2016-11-29 15:00:51 +08002424 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2425 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002427 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002428 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002429 }
2430
2431 if (border != 0)
2432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002433 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002434 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002435 }
2436
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002437 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002438 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002439 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002441 }
2442
Jamie Madille98b1b52018-03-08 09:47:23 -05002443 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002444 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002445 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002446 {
Geoff Langb1196682014-07-23 13:47:29 -04002447 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002448 }
2449
Jamie Madille98b1b52018-03-08 09:47:23 -05002450 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002451 {
Geoff Langb1196682014-07-23 13:47:29 -04002452 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002453 }
2454
Martin Radev138064f2016-07-15 12:03:41 +03002455 if (readFramebuffer->getReadBufferState() == GL_NONE)
2456 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002458 return false;
2459 }
2460
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002461 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2462 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002463 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002464 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002465 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2466 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002467 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002469 return false;
2470 }
2471
Martin Radev04e2c3b2017-07-27 16:54:35 +03002472 // ANGLE_multiview spec, Revision 1:
2473 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2474 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2475 // is not NONE.
2476 if (source->getMultiviewLayout() != GL_NONE)
2477 {
2478 context->handleError(InvalidFramebufferOperation()
2479 << "The active read framebuffer object has multiview attachments.");
2480 return false;
2481 }
2482
Geoff Langaae65a42014-05-26 12:43:44 -04002483 const gl::Caps &caps = context->getCaps();
2484
Geoff Langaae65a42014-05-26 12:43:44 -04002485 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002486 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002487 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002488 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002489 maxDimension = caps.max2DTextureSize;
2490 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002491
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002492 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002493 maxDimension = caps.maxCubeMapTextureSize;
2494 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002495
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002496 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002497 maxDimension = caps.maxRectangleTextureSize;
2498 break;
2499
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002500 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002501 maxDimension = caps.max2DTextureSize;
2502 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002503
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002504 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 maxDimension = caps.max3DTextureSize;
2506 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002507
He Yunchaoced53ae2016-11-29 15:00:51 +08002508 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002509 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002510 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002511 }
2512
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002513 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002514 if (!texture)
2515 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002516 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002517 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002518 }
2519
Geoff Lang69cce582015-09-17 13:20:36 -04002520 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002522 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002524 }
2525
Geoff Langca271392017-04-05 12:30:00 -04002526 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002527 isSubImage ? *texture->getFormat(target, level).info
2528 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002529
Geoff Lang966c9402017-04-18 12:38:27 -04002530 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002532 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002533 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002534 }
2535
2536 if (isSubImage)
2537 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002538 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2539 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2540 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002542 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002543 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002544 }
2545 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002546 else
2547 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002548 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002549 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002550 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002551 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002552 }
2553
Geoff Langeb66a6e2016-10-31 13:06:12 -04002554 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002555 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002556 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002557 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002558 }
2559
2560 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002561 if (static_cast<int>(width) > maxLevelDimension ||
2562 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002563 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002564 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002565 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002566 }
2567 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002568
Jamie Madill0c8abca2016-07-22 20:21:26 -04002569 if (textureFormatOut)
2570 {
2571 *textureFormatOut = texture->getFormat(target, level);
2572 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002573
2574 // Detect texture copying feedback loops for WebGL.
2575 if (context->getExtensions().webglCompatibility)
2576 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002577 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002578 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002579 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002580 return false;
2581 }
2582 }
2583
Jamie Madill560a8d82014-05-21 13:06:20 -04002584 return true;
2585}
2586
Jamie Madill5b772312018-03-08 20:28:32 -05002587bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002588{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002589 const Extensions &extensions = context->getExtensions();
2590
Jamie Madill1aeb1312014-06-20 13:21:25 -04002591 switch (mode)
2592 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002593 case GL_POINTS:
2594 case GL_LINES:
2595 case GL_LINE_LOOP:
2596 case GL_LINE_STRIP:
2597 case GL_TRIANGLES:
2598 case GL_TRIANGLE_STRIP:
2599 case GL_TRIANGLE_FAN:
2600 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002601
2602 case GL_LINES_ADJACENCY_EXT:
2603 case GL_LINE_STRIP_ADJACENCY_EXT:
2604 case GL_TRIANGLES_ADJACENCY_EXT:
2605 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2606 if (!extensions.geometryShader)
2607 {
2608 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2609 return false;
2610 }
2611 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002612 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002613 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002614 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002615 }
2616
Jamie Madill250d33f2014-06-06 17:09:03 -04002617 if (count < 0)
2618 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002619 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002620 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002621 }
2622
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002623 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002624
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002625 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2626 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2627 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2628 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002629 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002630 // Check for mapped buffers
2631 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002632 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002633 {
2634 context->handleError(InvalidOperation());
2635 return false;
2636 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002637 }
2638
Jamie Madillcbcde722017-01-06 14:50:00 -05002639 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2640 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002641 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002642 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002643 {
Ken Russellb9f92502018-01-27 19:00:26 -08002644 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002645 const FramebufferAttachment *dsAttachment =
2646 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002647 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2648 ASSERT(stencilBits <= 8);
2649
Jinyoung Hur85769f02015-10-20 17:08:44 -04002650 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002651 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002652 {
Ken Russellb9f92502018-01-27 19:00:26 -08002653 GLuint maxStencilValue = (1 << stencilBits) - 1;
2654
2655 bool differentRefs =
2656 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2657 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2658 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2659 (depthStencilState.stencilBackWritemask & maxStencilValue);
2660 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2661 (depthStencilState.stencilBackMask & maxStencilValue);
2662
2663 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002664 {
Ken Russellb9f92502018-01-27 19:00:26 -08002665 if (!extensions.webglCompatibility)
2666 {
2667 ERR() << "This ANGLE implementation does not support separate front/back "
2668 "stencil writemasks, reference values, or stencil mask values.";
2669 }
2670 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2671 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002672 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002673 }
Jamie Madillac528012014-06-20 13:21:23 -04002674 }
2675
Jamie Madill427064d2018-04-13 16:20:34 -04002676 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002677 {
Geoff Langb1196682014-07-23 13:47:29 -04002678 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002679 }
2680
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002681 // If we are running GLES1, there is no current program.
2682 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002683 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002684
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002685 gl::Program *program = state.getProgram();
2686 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002687 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002688 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002689 return false;
2690 }
Martin Radev7e69f762017-07-27 14:54:13 +03002691
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002692 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2693 // vertex shader stage or fragment shader stage is a undefined behaviour.
2694 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2695 // produce undefined result.
2696 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2697 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002698 {
2699 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002700 << "It is a undefined behaviour to render without "
2701 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002702 return false;
2703 }
Martin Radevffe754b2017-07-31 10:38:07 +03002704
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002705 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002706 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002707 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002708 return false;
2709 }
2710
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002711 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002712 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002713 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2714 const int framebufferNumViews = framebuffer->getNumViews();
2715 if (framebufferNumViews != programNumViews)
2716 {
2717 context->handleError(InvalidOperation()
2718 << "The number of views in the active program "
2719 "and draw framebuffer does not match.");
2720 return false;
2721 }
2722
2723 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2724 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2725 framebufferNumViews > 1)
2726 {
2727 context->handleError(InvalidOperation()
2728 << "There is an active transform feedback object "
2729 "when the number of views in the active draw "
2730 "framebuffer is greater than 1.");
2731 return false;
2732 }
2733
2734 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2735 state.isQueryActive(QueryType::TimeElapsed))
2736 {
2737 context->handleError(InvalidOperation()
2738 << "There is an active query for target "
2739 "GL_TIME_ELAPSED_EXT when the number of "
2740 "views in the active draw framebuffer is "
2741 "greater than 1.");
2742 return false;
2743 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002744 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002745
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002746 // Do geometry shader specific validations
2747 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002748 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002749 if (!IsCompatibleDrawModeWithGeometryShader(
2750 mode, program->getGeometryShaderInputPrimitiveType()))
2751 {
2752 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2753 IncompatibleDrawModeAgainstGeometryShader);
2754 return false;
2755 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002756 }
Geoff Lange0cff192017-05-30 13:04:56 -04002757
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002758 // Uniform buffer validation
2759 for (unsigned int uniformBlockIndex = 0;
2760 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002761 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002762 const gl::InterfaceBlock &uniformBlock =
2763 program->getUniformBlockByIndex(uniformBlockIndex);
2764 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2765 const OffsetBindingPointer<Buffer> &uniformBuffer =
2766 state.getIndexedUniformBuffer(blockBinding);
2767
2768 if (uniformBuffer.get() == nullptr)
2769 {
2770 // undefined behaviour
2771 context->handleError(
2772 InvalidOperation()
2773 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2774 return false;
2775 }
2776
2777 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2778 if (uniformBufferSize < uniformBlock.dataSize)
2779 {
2780 // undefined behaviour
2781 context->handleError(
2782 InvalidOperation()
2783 << "It is undefined behaviour to use a uniform buffer that is too small.");
2784 return false;
2785 }
2786
2787 if (extensions.webglCompatibility &&
2788 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2789 {
2790 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2791 UniformBufferBoundForTransformFeedback);
2792 return false;
2793 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002794 }
2795
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002796 // Do some additonal WebGL-specific validation
2797 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002798 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002799 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2800 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2801 transformFeedbackObject->buffersBoundForOtherUse())
2802 {
2803 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2804 TransformFeedbackBufferDoubleBound);
2805 return false;
2806 }
2807 // Detect rendering feedback loops for WebGL.
2808 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2809 {
2810 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2811 return false;
2812 }
2813
2814 // Detect that the vertex shader input types match the attribute types
2815 if (!ValidateVertexShaderAttributeTypeMatch(context))
2816 {
2817 return false;
2818 }
2819
2820 // Detect that the color buffer types match the fragment shader output types
2821 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2822 {
2823 return false;
2824 }
Geoff Lange0cff192017-05-30 13:04:56 -04002825 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002826 }
2827
Jamie Madill9fdaa492018-02-16 10:52:11 -05002828 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002829}
2830
Jamie Madill5b772312018-03-08 20:28:32 -05002831bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002832 GLenum mode,
2833 GLint first,
2834 GLsizei count,
2835 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002836{
Jamie Madillfd716582014-06-06 17:09:04 -04002837 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002839 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002840 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002841 }
2842
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002843 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002844 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002845 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002846 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002847 {
James Darpinian30b604d2018-03-12 17:26:57 -07002848 if (curTransformFeedback->getPrimitiveMode() != mode)
2849 {
2850 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2851 // that does not match the current transform feedback object's draw mode (if transform
2852 // feedback
2853 // is active), (3.0.2, section 2.14, pg 86)
2854 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2855 return false;
2856 }
2857
2858 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2859 {
2860 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2861 return false;
2862 }
Jamie Madillfd716582014-06-06 17:09:04 -04002863 }
2864
Jiajia Qind9671222016-11-29 16:30:31 +08002865 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002866 {
2867 return false;
2868 }
2869
Corentin Wallez71168a02016-12-19 15:11:18 -08002870 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002871 // - first < 0 has been checked as an error condition.
2872 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002873 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002874 ASSERT(first >= 0);
2875 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002876 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002877 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2878 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2879 {
2880 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2881 return false;
2882 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002883
Jamie Madill9fdaa492018-02-16 10:52:11 -05002884 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2885 {
2886 return false;
2887 }
Jamie Madillfd716582014-06-06 17:09:04 -04002888 }
2889
2890 return true;
2891}
2892
He Yunchaoced53ae2016-11-29 15:00:51 +08002893bool ValidateDrawArraysInstancedANGLE(Context *context,
2894 GLenum mode,
2895 GLint first,
2896 GLsizei count,
2897 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002898{
Geoff Lang63c5a592017-09-27 14:08:16 -04002899 if (!context->getExtensions().instancedArrays)
2900 {
2901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2902 return false;
2903 }
2904
Corentin Wallez170efbf2017-05-02 13:45:01 -04002905 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002906 {
2907 return false;
2908 }
2909
Corentin Wallez0dc97812017-06-22 14:38:44 -04002910 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002911}
2912
Jamie Madill5b772312018-03-08 20:28:32 -05002913bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002914{
Jamie Madill250d33f2014-06-06 17:09:03 -04002915 switch (type)
2916 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002917 case GL_UNSIGNED_BYTE:
2918 case GL_UNSIGNED_SHORT:
2919 break;
2920 case GL_UNSIGNED_INT:
2921 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2922 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002923 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002924 return false;
2925 }
2926 break;
2927 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002928 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002929 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002930 }
2931
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002932 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002933
2934 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002935 if (curTransformFeedback && curTransformFeedback->isActive() &&
2936 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002937 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002938 // It is an invalid operation to call DrawElements, DrawRangeElements or
2939 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002940 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002941 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002942 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002943 }
2944
Jiajia Qind9671222016-11-29 16:30:31 +08002945 return true;
2946}
2947
Jamie Madill5b772312018-03-08 20:28:32 -05002948bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002949 GLenum mode,
2950 GLsizei count,
2951 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002952 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002953 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002954{
2955 if (!ValidateDrawElementsBase(context, type))
2956 return false;
2957
2958 const State &state = context->getGLState();
2959
Corentin Wallez170efbf2017-05-02 13:45:01 -04002960 if (!ValidateDrawBase(context, mode, count))
2961 {
2962 return false;
2963 }
2964
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002965 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2966 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2967 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2968 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002969 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002970 // Check for mapped buffers
2971 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002972 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002973 {
2974 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2975 return false;
2976 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002977 }
2978
He Yunchaoced53ae2016-11-29 15:00:51 +08002979 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002980 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002981
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002982 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2983
2984 if (context->getExtensions().webglCompatibility)
2985 {
2986 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2987 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2988 {
2989 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2990 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2991 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002992 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002993 return false;
2994 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002995
2996 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2997 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2998 // error is generated.
2999 if (reinterpret_cast<intptr_t>(indices) < 0)
3000 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003001 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003002 return false;
3003 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003004 }
3005
3006 if (context->getExtensions().webglCompatibility ||
3007 !context->getGLState().areClientArraysEnabled())
3008 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003009 if (!elementArrayBuffer && count > 0)
3010 {
3011 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3012 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3013 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003014 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003015 return false;
3016 }
3017 }
3018
Jamie Madill9fdaa492018-02-16 10:52:11 -05003019 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003020 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003021 // This is an application error that would normally result in a crash, but we catch it and
3022 // return an error
3023 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3024 return false;
3025 }
3026
3027 if (count > 0 && elementArrayBuffer)
3028 {
3029 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3030 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3031 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3032 constexpr uint64_t kMaxTypeSize = 8;
3033 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3034 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3035 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3036
3037 uint64_t typeSize = typeBytes;
3038 uint64_t elementCount = static_cast<uint64_t>(count);
3039 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3040
3041 // Doing the multiplication here is overflow-safe
3042 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3043
3044 // The offset can be any value, check for overflows
3045 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3046 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003047 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003048 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3049 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003050 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003051
3052 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3053 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003054 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3056 return false;
3057 }
3058
3059 ASSERT(isPow2(typeSize) && typeSize > 0);
3060 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3061 {
3062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003063 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003064 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003065
3066 if (context->getExtensions().webglCompatibility &&
3067 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3068 {
3069 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3070 ElementArrayBufferBoundForTransformFeedback);
3071 return false;
3072 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003073 }
3074
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003075 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003076 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003077 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3078 // access is enabled.
3079 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3080 {
3081 return false;
3082 }
3083 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003084 else if (count == 0)
3085 {
3086 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3087 // count.
3088 if (!ValidateDrawAttribs(context, 0, 0, 0))
3089 {
3090 return false;
3091 }
3092 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003093 else
3094 {
3095 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003096 const DrawCallParams &params = context->getParams<DrawCallParams>();
3097 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3098 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003099
3100 // If we use an index greater than our maximum supported index range, return an error.
3101 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3102 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003103 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003104 {
3105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3106 return false;
3107 }
3108
Jamie Madill6f5444d2018-03-14 10:08:11 -04003109 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3110 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003111 {
3112 return false;
3113 }
3114
3115 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003116 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003117 }
3118
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003119 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003120}
3121
Jamie Madill5b772312018-03-08 20:28:32 -05003122bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003123 GLenum mode,
3124 GLsizei count,
3125 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003126 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003127 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003128{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003129 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003130}
3131
Geoff Lang3edfe032015-09-04 16:38:24 -04003132bool ValidateDrawElementsInstancedANGLE(Context *context,
3133 GLenum mode,
3134 GLsizei count,
3135 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003136 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003137 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003138{
Geoff Lang63c5a592017-09-27 14:08:16 -04003139 if (!context->getExtensions().instancedArrays)
3140 {
3141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3142 return false;
3143 }
3144
Corentin Wallez170efbf2017-05-02 13:45:01 -04003145 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003146 {
3147 return false;
3148 }
3149
Corentin Wallez0dc97812017-06-22 14:38:44 -04003150 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003151}
3152
He Yunchaoced53ae2016-11-29 15:00:51 +08003153bool ValidateFramebufferTextureBase(Context *context,
3154 GLenum target,
3155 GLenum attachment,
3156 GLuint texture,
3157 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003158{
Geoff Lange8afa902017-09-27 15:00:43 -04003159 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003162 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003163 }
3164
3165 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003166 {
3167 return false;
3168 }
3169
Jamie Madill55ec3b12014-07-03 10:38:57 -04003170 if (texture != 0)
3171 {
3172 gl::Texture *tex = context->getTexture(texture);
3173
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003174 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003176 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003177 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003178 }
3179
3180 if (level < 0)
3181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003182 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003183 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003184 }
3185 }
3186
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003187 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003188 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003189
Jamie Madill84115c92015-04-23 15:00:07 -04003190 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003192 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003193 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003194 }
3195
3196 return true;
3197}
3198
Geoff Langb1196682014-07-23 13:47:29 -04003199bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003200{
3201 if (program == 0)
3202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003203 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003204 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003205 }
3206
Dian Xiang769769a2015-09-09 15:20:08 -07003207 gl::Program *programObject = GetValidProgram(context, program);
3208 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003209 {
3210 return false;
3211 }
3212
Jamie Madill0063c512014-08-25 15:47:53 -04003213 if (!programObject || !programObject->isLinked())
3214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003216 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003217 }
3218
Geoff Lang7dd2e102014-11-10 15:19:26 -05003219 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003221 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003222 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003223 }
3224
Jamie Madill0063c512014-08-25 15:47:53 -04003225 return true;
3226}
3227
Geoff Langf41d0ee2016-10-07 13:04:23 -04003228static bool ValidateSizedGetUniform(Context *context,
3229 GLuint program,
3230 GLint location,
3231 GLsizei bufSize,
3232 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003233{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003234 if (length)
3235 {
3236 *length = 0;
3237 }
3238
Jamie Madill78f41802014-08-25 15:47:55 -04003239 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003240 {
Jamie Madill78f41802014-08-25 15:47:55 -04003241 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003242 }
3243
Geoff Langf41d0ee2016-10-07 13:04:23 -04003244 if (bufSize < 0)
3245 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003246 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003247 return false;
3248 }
3249
Jamie Madilla502c742014-08-28 17:19:13 -04003250 gl::Program *programObject = context->getProgram(program);
3251 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003252
Jamie Madill78f41802014-08-25 15:47:55 -04003253 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003254 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003255 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003256 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003257 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003259 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003260 }
3261
Geoff Langf41d0ee2016-10-07 13:04:23 -04003262 if (length)
3263 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003264 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003265 }
3266
Jamie Madill0063c512014-08-25 15:47:53 -04003267 return true;
3268}
3269
He Yunchaoced53ae2016-11-29 15:00:51 +08003270bool ValidateGetnUniformfvEXT(Context *context,
3271 GLuint program,
3272 GLint location,
3273 GLsizei bufSize,
3274 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003275{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003276 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003277}
3278
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003279bool ValidateGetnUniformfvRobustANGLE(Context *context,
3280 GLuint program,
3281 GLint location,
3282 GLsizei bufSize,
3283 GLsizei *length,
3284 GLfloat *params)
3285{
3286 UNIMPLEMENTED();
3287 return false;
3288}
3289
He Yunchaoced53ae2016-11-29 15:00:51 +08003290bool ValidateGetnUniformivEXT(Context *context,
3291 GLuint program,
3292 GLint location,
3293 GLsizei bufSize,
3294 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003295{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003296 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3297}
3298
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003299bool ValidateGetnUniformivRobustANGLE(Context *context,
3300 GLuint program,
3301 GLint location,
3302 GLsizei bufSize,
3303 GLsizei *length,
3304 GLint *params)
3305{
3306 UNIMPLEMENTED();
3307 return false;
3308}
3309
3310bool ValidateGetnUniformuivRobustANGLE(Context *context,
3311 GLuint program,
3312 GLint location,
3313 GLsizei bufSize,
3314 GLsizei *length,
3315 GLuint *params)
3316{
3317 UNIMPLEMENTED();
3318 return false;
3319}
3320
Geoff Langf41d0ee2016-10-07 13:04:23 -04003321bool ValidateGetUniformfvRobustANGLE(Context *context,
3322 GLuint program,
3323 GLint location,
3324 GLsizei bufSize,
3325 GLsizei *length,
3326 GLfloat *params)
3327{
3328 if (!ValidateRobustEntryPoint(context, bufSize))
3329 {
3330 return false;
3331 }
3332
Brandon Jonesd1049182018-03-28 10:02:20 -07003333 GLsizei writeLength = 0;
3334
Geoff Langf41d0ee2016-10-07 13:04:23 -04003335 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003336 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3337 {
3338 return false;
3339 }
3340
3341 SetRobustLengthParam(length, writeLength);
3342
3343 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003344}
3345
3346bool ValidateGetUniformivRobustANGLE(Context *context,
3347 GLuint program,
3348 GLint location,
3349 GLsizei bufSize,
3350 GLsizei *length,
3351 GLint *params)
3352{
3353 if (!ValidateRobustEntryPoint(context, bufSize))
3354 {
3355 return false;
3356 }
3357
Brandon Jonesd1049182018-03-28 10:02:20 -07003358 GLsizei writeLength = 0;
3359
Geoff Langf41d0ee2016-10-07 13:04:23 -04003360 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003361 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3362 {
3363 return false;
3364 }
3365
3366 SetRobustLengthParam(length, writeLength);
3367
3368 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003369}
3370
3371bool ValidateGetUniformuivRobustANGLE(Context *context,
3372 GLuint program,
3373 GLint location,
3374 GLsizei bufSize,
3375 GLsizei *length,
3376 GLuint *params)
3377{
3378 if (!ValidateRobustEntryPoint(context, bufSize))
3379 {
3380 return false;
3381 }
3382
3383 if (context->getClientMajorVersion() < 3)
3384 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003385 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003386 return false;
3387 }
3388
Brandon Jonesd1049182018-03-28 10:02:20 -07003389 GLsizei writeLength = 0;
3390
Geoff Langf41d0ee2016-10-07 13:04:23 -04003391 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003392 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3393 {
3394 return false;
3395 }
3396
3397 SetRobustLengthParam(length, writeLength);
3398
3399 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003400}
3401
He Yunchaoced53ae2016-11-29 15:00:51 +08003402bool ValidateDiscardFramebufferBase(Context *context,
3403 GLenum target,
3404 GLsizei numAttachments,
3405 const GLenum *attachments,
3406 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003407{
3408 if (numAttachments < 0)
3409 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003410 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003411 return false;
3412 }
3413
3414 for (GLsizei i = 0; i < numAttachments; ++i)
3415 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003416 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003417 {
3418 if (defaultFramebuffer)
3419 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003420 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003421 return false;
3422 }
3423
3424 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003426 context->handleError(InvalidOperation() << "Requested color attachment is "
3427 "greater than the maximum supported "
3428 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003429 return false;
3430 }
3431 }
3432 else
3433 {
3434 switch (attachments[i])
3435 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003436 case GL_DEPTH_ATTACHMENT:
3437 case GL_STENCIL_ATTACHMENT:
3438 case GL_DEPTH_STENCIL_ATTACHMENT:
3439 if (defaultFramebuffer)
3440 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003441 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3442 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003443 return false;
3444 }
3445 break;
3446 case GL_COLOR:
3447 case GL_DEPTH:
3448 case GL_STENCIL:
3449 if (!defaultFramebuffer)
3450 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003451 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3452 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003453 return false;
3454 }
3455 break;
3456 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003457 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003458 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003459 }
3460 }
3461 }
3462
3463 return true;
3464}
3465
Austin Kinross6ee1e782015-05-29 17:05:37 -07003466bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3467{
Jamie Madill007530e2017-12-28 14:27:04 -05003468 if (!context->getExtensions().debugMarker)
3469 {
3470 // The debug marker calls should not set error state
3471 // However, it seems reasonable to set an error state if the extension is not enabled
3472 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3473 return false;
3474 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003475
Jamie Madill007530e2017-12-28 14:27:04 -05003476 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003477 if (length < 0)
3478 {
3479 return false;
3480 }
3481
3482 if (marker == nullptr)
3483 {
3484 return false;
3485 }
3486
3487 return true;
3488}
3489
3490bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3491{
Jamie Madill007530e2017-12-28 14:27:04 -05003492 if (!context->getExtensions().debugMarker)
3493 {
3494 // The debug marker calls should not set error state
3495 // However, it seems reasonable to set an error state if the extension is not enabled
3496 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3497 return false;
3498 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003499
Jamie Madill007530e2017-12-28 14:27:04 -05003500 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003501 if (length < 0)
3502 {
3503 return false;
3504 }
3505
3506 if (length > 0 && marker == nullptr)
3507 {
3508 return false;
3509 }
3510
3511 return true;
3512}
3513
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003514bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003515{
Geoff Langa8406172015-07-21 16:53:39 -04003516 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003518 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003519 return false;
3520 }
3521
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003522 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003523 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003524 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003525 if (!context->getExtensions().eglImage)
3526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003527 context->handleError(InvalidEnum()
3528 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003529 }
3530 break;
3531
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003532 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003533 if (!context->getExtensions().eglImageExternal)
3534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003535 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3536 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003537 }
Geoff Langa8406172015-07-21 16:53:39 -04003538 break;
3539
3540 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003541 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003542 return false;
3543 }
3544
Jamie Madill007530e2017-12-28 14:27:04 -05003545 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3546
Jamie Madill61e16b42017-06-19 11:13:23 -04003547 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003548 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003550 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003551 return false;
3552 }
3553
Jamie Madill007530e2017-12-28 14:27:04 -05003554 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003555 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003556 context->handleError(InvalidOperation()
3557 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003558 return false;
3559 }
3560
Geoff Langca271392017-04-05 12:30:00 -04003561 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003562 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003563 if (!textureCaps.texturable)
3564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003565 context->handleError(InvalidOperation()
3566 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003567 return false;
3568 }
3569
Geoff Langdcab33b2015-07-21 13:03:16 -04003570 return true;
3571}
3572
3573bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003574 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003575 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003576{
Geoff Langa8406172015-07-21 16:53:39 -04003577 if (!context->getExtensions().eglImage)
3578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003579 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003580 return false;
3581 }
3582
3583 switch (target)
3584 {
3585 case GL_RENDERBUFFER:
3586 break;
3587
3588 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003589 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003590 return false;
3591 }
3592
Jamie Madill007530e2017-12-28 14:27:04 -05003593 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3594
Jamie Madill61e16b42017-06-19 11:13:23 -04003595 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003596 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003598 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003599 return false;
3600 }
3601
Geoff Langca271392017-04-05 12:30:00 -04003602 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003603 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003604 if (!textureCaps.renderable)
3605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003606 context->handleError(InvalidOperation()
3607 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003608 return false;
3609 }
3610
Geoff Langdcab33b2015-07-21 13:03:16 -04003611 return true;
3612}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003613
3614bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3615{
Geoff Lang36167ab2015-12-07 10:27:14 -05003616 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003617 {
3618 // The default VAO should always exist
3619 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003621 return false;
3622 }
3623
3624 return true;
3625}
3626
Geoff Langc5629752015-12-07 16:29:04 -05003627bool ValidateProgramBinaryBase(Context *context,
3628 GLuint program,
3629 GLenum binaryFormat,
3630 const void *binary,
3631 GLint length)
3632{
3633 Program *programObject = GetValidProgram(context, program);
3634 if (programObject == nullptr)
3635 {
3636 return false;
3637 }
3638
3639 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3640 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3641 programBinaryFormats.end())
3642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003643 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003644 return false;
3645 }
3646
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003647 if (context->hasActiveTransformFeedback(program))
3648 {
3649 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003650 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3651 "is associated with an active transform "
3652 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003653 return false;
3654 }
3655
Geoff Langc5629752015-12-07 16:29:04 -05003656 return true;
3657}
3658
3659bool ValidateGetProgramBinaryBase(Context *context,
3660 GLuint program,
3661 GLsizei bufSize,
3662 GLsizei *length,
3663 GLenum *binaryFormat,
3664 void *binary)
3665{
3666 Program *programObject = GetValidProgram(context, program);
3667 if (programObject == nullptr)
3668 {
3669 return false;
3670 }
3671
3672 if (!programObject->isLinked())
3673 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003675 return false;
3676 }
3677
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003678 if (context->getCaps().programBinaryFormats.empty())
3679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003680 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003681 return false;
3682 }
3683
Geoff Langc5629752015-12-07 16:29:04 -05003684 return true;
3685}
Jamie Madillc29968b2016-01-20 11:17:23 -05003686
Jamie Madill5b772312018-03-08 20:28:32 -05003687bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003688{
3689 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003690 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003691 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003692 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3693 return false;
3694 }
3695 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3696 {
3697 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003698 return false;
3699 }
3700
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003701 ASSERT(context->getGLState().getDrawFramebuffer());
3702 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003703 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3704
3705 // This should come first before the check for the default frame buffer
3706 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3707 // rather than INVALID_OPERATION
3708 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3709 {
3710 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3711
3712 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003713 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3714 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003715 {
3716 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003717 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3718 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3719 // 3.1 is still a bit ambiguous about the error, but future specs are
3720 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003721 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003722 return false;
3723 }
3724 else if (bufs[colorAttachment] >= maxColorAttachment)
3725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003726 context->handleError(InvalidOperation()
3727 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003728 return false;
3729 }
3730 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3731 frameBufferId != 0)
3732 {
3733 // INVALID_OPERATION-GL is bound to buffer and ith argument
3734 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 context->handleError(InvalidOperation()
3736 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003737 return false;
3738 }
3739 }
3740
3741 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3742 // and n is not 1 or bufs is bound to value other than BACK and NONE
3743 if (frameBufferId == 0)
3744 {
3745 if (n != 1)
3746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003747 context->handleError(InvalidOperation()
3748 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003749 return false;
3750 }
3751
3752 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 context->handleError(
3755 InvalidOperation()
3756 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003757 return false;
3758 }
3759 }
3760
3761 return true;
3762}
3763
Geoff Lang496c02d2016-10-20 11:38:11 -07003764bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003765 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003766 GLenum pname,
3767 GLsizei *length,
3768 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003769{
Geoff Lang496c02d2016-10-20 11:38:11 -07003770 if (length)
3771 {
3772 *length = 0;
3773 }
3774
3775 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3776 {
3777 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 InvalidOperation()
3779 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003780 return false;
3781 }
3782
Corentin Walleze4477002017-12-01 14:39:58 -05003783 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003784 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003785 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003786 return false;
3787 }
3788
Geoff Lang496c02d2016-10-20 11:38:11 -07003789 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003790 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003791 case GL_BUFFER_MAP_POINTER:
3792 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003793
Geoff Lang496c02d2016-10-20 11:38:11 -07003794 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003795 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003796 return false;
3797 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003798
3799 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3800 // target bound to zero generate an INVALID_OPERATION error."
3801 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003802 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003804 context->handleError(InvalidOperation()
3805 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003806 return false;
3807 }
3808
Geoff Lang496c02d2016-10-20 11:38:11 -07003809 if (length)
3810 {
3811 *length = 1;
3812 }
3813
Olli Etuaho4f667482016-03-30 15:56:35 +03003814 return true;
3815}
3816
Corentin Wallez336129f2017-10-17 15:55:40 -04003817bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003818{
Corentin Walleze4477002017-12-01 14:39:58 -05003819 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003820 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003821 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003822 return false;
3823 }
3824
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003825 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003826
3827 if (buffer == nullptr || !buffer->isMapped())
3828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003829 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003830 return false;
3831 }
3832
3833 return true;
3834}
3835
3836bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003837 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003838 GLintptr offset,
3839 GLsizeiptr length,
3840 GLbitfield access)
3841{
Corentin Walleze4477002017-12-01 14:39:58 -05003842 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003843 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003844 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003845 return false;
3846 }
3847
Brandon Jones6cad5662017-06-14 13:25:13 -07003848 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003849 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003850 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3851 return false;
3852 }
3853
3854 if (length < 0)
3855 {
3856 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003857 return false;
3858 }
3859
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003860 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003861
3862 if (!buffer)
3863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003864 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003865 return false;
3866 }
3867
3868 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003869 CheckedNumeric<size_t> checkedOffset(offset);
3870 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003871
Jamie Madille2e406c2016-06-02 13:04:10 -04003872 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003873 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003874 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003875 return false;
3876 }
3877
3878 // Check for invalid bits in the mask
3879 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3880 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3881 GL_MAP_UNSYNCHRONIZED_BIT;
3882
3883 if (access & ~(allAccessBits))
3884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003885 context->handleError(InvalidValue()
3886 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003887 return false;
3888 }
3889
3890 if (length == 0)
3891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003892 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003893 return false;
3894 }
3895
3896 if (buffer->isMapped())
3897 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003898 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003899 return false;
3900 }
3901
3902 // Check for invalid bit combinations
3903 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3904 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003905 context->handleError(InvalidOperation()
3906 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003907 return false;
3908 }
3909
3910 GLbitfield writeOnlyBits =
3911 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3912
3913 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003915 context->handleError(InvalidOperation()
3916 << "Invalid access bits when mapping buffer for reading: 0x"
3917 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003918 return false;
3919 }
3920
3921 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003923 context->handleError(
3924 InvalidOperation()
3925 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003926 return false;
3927 }
Geoff Lang79f71042017-08-14 16:43:43 -04003928
3929 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003930}
3931
3932bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003933 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003934 GLintptr offset,
3935 GLsizeiptr length)
3936{
Brandon Jones6cad5662017-06-14 13:25:13 -07003937 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003938 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003939 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3940 return false;
3941 }
3942
3943 if (length < 0)
3944 {
3945 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003946 return false;
3947 }
3948
Corentin Walleze4477002017-12-01 14:39:58 -05003949 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003950 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003951 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003952 return false;
3953 }
3954
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003955 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003956
3957 if (buffer == nullptr)
3958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003959 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003960 return false;
3961 }
3962
3963 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003965 context->handleError(InvalidOperation()
3966 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003967 return false;
3968 }
3969
3970 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003971 CheckedNumeric<size_t> checkedOffset(offset);
3972 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003973
Jamie Madille2e406c2016-06-02 13:04:10 -04003974 if (!checkedSize.IsValid() ||
3975 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003977 context->handleError(InvalidValue()
3978 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003979 return false;
3980 }
3981
3982 return true;
3983}
3984
Olli Etuaho41997e72016-03-10 13:38:39 +02003985bool ValidateGenOrDelete(Context *context, GLint n)
3986{
3987 if (n < 0)
3988 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003989 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003990 return false;
3991 }
3992 return true;
3993}
3994
Jamie Madill5b772312018-03-08 20:28:32 -05003995bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003996{
3997 if (!context->getExtensions().robustClientMemory)
3998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003999 context->handleError(InvalidOperation()
4000 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004001 return false;
4002 }
4003
4004 if (bufSize < 0)
4005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004006 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004007 return false;
4008 }
4009
4010 return true;
4011}
4012
Jamie Madill5b772312018-03-08 20:28:32 -05004013bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004014{
4015 if (bufSize < numParams)
4016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004017 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4018 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004019 return false;
4020 }
4021
4022 return true;
4023}
4024
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004025bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004026 GLenum target,
4027 GLenum attachment,
4028 GLenum pname,
4029 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004030{
Geoff Lange8afa902017-09-27 15:00:43 -04004031 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004033 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004034 return false;
4035 }
4036
4037 int clientVersion = context->getClientMajorVersion();
4038
4039 switch (pname)
4040 {
4041 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4042 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4043 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4044 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4045 break;
4046
Martin Radeve5285d22017-07-14 16:23:53 +03004047 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4048 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4049 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4050 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4051 if (clientVersion < 3 || !context->getExtensions().multiview)
4052 {
4053 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4054 return false;
4055 }
4056 break;
4057
Geoff Langff5b2d52016-09-07 11:32:23 -04004058 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4059 if (clientVersion < 3 && !context->getExtensions().sRGB)
4060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004061 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004062 return false;
4063 }
4064 break;
4065
4066 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4067 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4068 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4069 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4070 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4071 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4072 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4073 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4074 if (clientVersion < 3)
4075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004076 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 return false;
4078 }
4079 break;
4080
4081 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004082 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004083 return false;
4084 }
4085
4086 // Determine if the attachment is a valid enum
4087 switch (attachment)
4088 {
4089 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004090 case GL_DEPTH:
4091 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004092 if (clientVersion < 3)
4093 {
Geoff Langfa125c92017-10-24 13:01:46 -04004094 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004095 return false;
4096 }
4097 break;
4098
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004099 case GL_DEPTH_STENCIL_ATTACHMENT:
4100 if (clientVersion < 3 && !context->isWebGL1())
4101 {
4102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4103 return false;
4104 }
4105 break;
4106
Geoff Langfa125c92017-10-24 13:01:46 -04004107 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004108 case GL_DEPTH_ATTACHMENT:
4109 case GL_STENCIL_ATTACHMENT:
4110 break;
4111
4112 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004113 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4114 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004115 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4116 {
Geoff Langfa125c92017-10-24 13:01:46 -04004117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004118 return false;
4119 }
4120 break;
4121 }
4122
4123 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4124 ASSERT(framebuffer);
4125
4126 if (framebuffer->id() == 0)
4127 {
4128 if (clientVersion < 3)
4129 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004130 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004131 return false;
4132 }
4133
4134 switch (attachment)
4135 {
4136 case GL_BACK:
4137 case GL_DEPTH:
4138 case GL_STENCIL:
4139 break;
4140
4141 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004142 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004143 return false;
4144 }
4145 }
4146 else
4147 {
4148 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4149 {
4150 // Valid attachment query
4151 }
4152 else
4153 {
4154 switch (attachment)
4155 {
4156 case GL_DEPTH_ATTACHMENT:
4157 case GL_STENCIL_ATTACHMENT:
4158 break;
4159
4160 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004161 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004163 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004164 return false;
4165 }
4166 break;
4167
4168 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004170 return false;
4171 }
4172 }
4173 }
4174
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004175 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004176 if (attachmentObject)
4177 {
4178 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4179 attachmentObject->type() == GL_TEXTURE ||
4180 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4181
4182 switch (pname)
4183 {
4184 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4185 if (attachmentObject->type() != GL_RENDERBUFFER &&
4186 attachmentObject->type() != GL_TEXTURE)
4187 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004188 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004189 return false;
4190 }
4191 break;
4192
4193 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4194 if (attachmentObject->type() != GL_TEXTURE)
4195 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004197 return false;
4198 }
4199 break;
4200
4201 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4202 if (attachmentObject->type() != GL_TEXTURE)
4203 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004204 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004205 return false;
4206 }
4207 break;
4208
4209 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4210 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4211 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004212 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004213 return false;
4214 }
4215 break;
4216
4217 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4218 if (attachmentObject->type() != GL_TEXTURE)
4219 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004220 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004221 return false;
4222 }
4223 break;
4224
4225 default:
4226 break;
4227 }
4228 }
4229 else
4230 {
4231 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4232 // is NONE, then querying any other pname will generate INVALID_ENUM.
4233
4234 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4235 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4236 // INVALID_OPERATION for all other pnames
4237
4238 switch (pname)
4239 {
4240 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4241 break;
4242
4243 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4244 if (clientVersion < 3)
4245 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004246 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004247 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004248 return false;
4249 }
4250 break;
4251
4252 default:
4253 if (clientVersion < 3)
4254 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004255 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004256 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004257 return false;
4258 }
4259 else
4260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004261 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004262 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004263 return false;
4264 }
4265 }
4266 }
4267
Martin Radeve5285d22017-07-14 16:23:53 +03004268 if (numParams)
4269 {
4270 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4271 {
4272 // Only when the viewport offsets are queried we can have a varying number of output
4273 // parameters.
4274 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4275 *numParams = numViews * 2;
4276 }
4277 else
4278 {
4279 // For all other queries we can have only one output parameter.
4280 *numParams = 1;
4281 }
4282 }
4283
Geoff Langff5b2d52016-09-07 11:32:23 -04004284 return true;
4285}
4286
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004287bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004288 GLenum target,
4289 GLenum attachment,
4290 GLenum pname,
4291 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004292 GLsizei *length,
4293 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004294{
4295 if (!ValidateRobustEntryPoint(context, bufSize))
4296 {
4297 return false;
4298 }
4299
Brandon Jonesd1049182018-03-28 10:02:20 -07004300 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004301 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004302 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004303 {
4304 return false;
4305 }
4306
Brandon Jonesd1049182018-03-28 10:02:20 -07004307 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004308 {
4309 return false;
4310 }
4311
Brandon Jonesd1049182018-03-28 10:02:20 -07004312 SetRobustLengthParam(length, numParams);
4313
Geoff Langff5b2d52016-09-07 11:32:23 -04004314 return true;
4315}
4316
Jamie Madill5b772312018-03-08 20:28:32 -05004317bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004318 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004319 GLenum pname,
4320 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004321 GLsizei *length,
4322 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004323{
4324 if (!ValidateRobustEntryPoint(context, bufSize))
4325 {
4326 return false;
4327 }
4328
Brandon Jonesd1049182018-03-28 10:02:20 -07004329 GLsizei numParams = 0;
4330
4331 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004332 {
4333 return false;
4334 }
4335
Brandon Jonesd1049182018-03-28 10:02:20 -07004336 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004337 {
4338 return false;
4339 }
4340
Brandon Jonesd1049182018-03-28 10:02:20 -07004341 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004342 return true;
4343}
4344
Jamie Madill5b772312018-03-08 20:28:32 -05004345bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004346 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004347 GLenum pname,
4348 GLsizei bufSize,
4349 GLsizei *length,
4350 GLint64 *params)
4351{
Brandon Jonesd1049182018-03-28 10:02:20 -07004352 GLsizei numParams = 0;
4353
Geoff Langebebe1c2016-10-14 12:01:31 -04004354 if (!ValidateRobustEntryPoint(context, bufSize))
4355 {
4356 return false;
4357 }
4358
Brandon Jonesd1049182018-03-28 10:02:20 -07004359 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -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 ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004375{
4376 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004377 if (numParams)
4378 {
4379 *numParams = 1;
4380 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004381
4382 Program *programObject = GetValidProgram(context, program);
4383 if (!programObject)
4384 {
4385 return false;
4386 }
4387
4388 switch (pname)
4389 {
4390 case GL_DELETE_STATUS:
4391 case GL_LINK_STATUS:
4392 case GL_VALIDATE_STATUS:
4393 case GL_INFO_LOG_LENGTH:
4394 case GL_ATTACHED_SHADERS:
4395 case GL_ACTIVE_ATTRIBUTES:
4396 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4397 case GL_ACTIVE_UNIFORMS:
4398 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4399 break;
4400
4401 case GL_PROGRAM_BINARY_LENGTH:
4402 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004404 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4405 "requires GL_OES_get_program_binary or "
4406 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004407 return false;
4408 }
4409 break;
4410
4411 case GL_ACTIVE_UNIFORM_BLOCKS:
4412 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4413 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4414 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4415 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4416 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4417 if (context->getClientMajorVersion() < 3)
4418 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004419 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004420 return false;
4421 }
4422 break;
4423
Yunchao He61afff12017-03-14 15:34:03 +08004424 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004425 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004426 if (context->getClientVersion() < Version(3, 1))
4427 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004429 return false;
4430 }
4431 break;
4432
Jiawei Shao6ae51612018-02-23 14:03:25 +08004433 case GL_COMPUTE_WORK_GROUP_SIZE:
4434 if (context->getClientVersion() < Version(3, 1))
4435 {
4436 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4437 return false;
4438 }
4439
4440 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4441 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4442 // program which has not been linked successfully, or which does not contain objects to
4443 // form a compute shader.
4444 if (!programObject->isLinked())
4445 {
4446 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4447 return false;
4448 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004449 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004450 {
4451 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4452 return false;
4453 }
4454 break;
4455
Jiawei Shao447bfac2018-03-14 14:23:40 +08004456 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4457 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4458 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4459 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4460 if (!context->getExtensions().geometryShader)
4461 {
4462 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4463 return false;
4464 }
4465
4466 // [EXT_geometry_shader] Chapter 7.12
4467 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4468 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4469 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4470 // successfully, or which does not contain objects to form a geometry shader.
4471 if (!programObject->isLinked())
4472 {
4473 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4474 return false;
4475 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004476 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004477 {
4478 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4479 return false;
4480 }
4481 break;
4482
Geoff Langff5b2d52016-09-07 11:32:23 -04004483 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004484 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004485 return false;
4486 }
4487
4488 return true;
4489}
4490
4491bool ValidateGetProgramivRobustANGLE(Context *context,
4492 GLuint program,
4493 GLenum pname,
4494 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004495 GLsizei *length,
4496 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004497{
4498 if (!ValidateRobustEntryPoint(context, bufSize))
4499 {
4500 return false;
4501 }
4502
Brandon Jonesd1049182018-03-28 10:02:20 -07004503 GLsizei numParams = 0;
4504
4505 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004506 {
4507 return false;
4508 }
4509
Brandon Jonesd1049182018-03-28 10:02:20 -07004510 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004511 {
4512 return false;
4513 }
4514
Brandon Jonesd1049182018-03-28 10:02:20 -07004515 SetRobustLengthParam(length, numParams);
4516
Geoff Langff5b2d52016-09-07 11:32:23 -04004517 return true;
4518}
4519
Geoff Lang740d9022016-10-07 11:20:52 -04004520bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4521 GLenum target,
4522 GLenum pname,
4523 GLsizei bufSize,
4524 GLsizei *length,
4525 GLint *params)
4526{
4527 if (!ValidateRobustEntryPoint(context, bufSize))
4528 {
4529 return false;
4530 }
4531
Brandon Jonesd1049182018-03-28 10:02:20 -07004532 GLsizei numParams = 0;
4533
4534 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004535 {
4536 return false;
4537 }
4538
Brandon Jonesd1049182018-03-28 10:02:20 -07004539 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004540 {
4541 return false;
4542 }
4543
Brandon Jonesd1049182018-03-28 10:02:20 -07004544 SetRobustLengthParam(length, numParams);
4545
Geoff Lang740d9022016-10-07 11:20:52 -04004546 return true;
4547}
4548
Geoff Langd7d0ed32016-10-07 11:33:51 -04004549bool ValidateGetShaderivRobustANGLE(Context *context,
4550 GLuint shader,
4551 GLenum pname,
4552 GLsizei bufSize,
4553 GLsizei *length,
4554 GLint *params)
4555{
4556 if (!ValidateRobustEntryPoint(context, bufSize))
4557 {
4558 return false;
4559 }
4560
Brandon Jonesd1049182018-03-28 10:02:20 -07004561 GLsizei numParams = 0;
4562
4563 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004564 {
4565 return false;
4566 }
4567
Brandon Jonesd1049182018-03-28 10:02:20 -07004568 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004569 {
4570 return false;
4571 }
4572
Brandon Jonesd1049182018-03-28 10:02:20 -07004573 SetRobustLengthParam(length, numParams);
4574
Geoff Langd7d0ed32016-10-07 11:33:51 -04004575 return true;
4576}
4577
Geoff Langc1984ed2016-10-07 12:41:00 -04004578bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004579 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004580 GLenum pname,
4581 GLsizei bufSize,
4582 GLsizei *length,
4583 GLfloat *params)
4584{
4585 if (!ValidateRobustEntryPoint(context, bufSize))
4586 {
4587 return false;
4588 }
4589
Brandon Jonesd1049182018-03-28 10:02:20 -07004590 GLsizei numParams = 0;
4591
4592 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004593 {
4594 return false;
4595 }
4596
Brandon Jonesd1049182018-03-28 10:02:20 -07004597 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004598 {
4599 return false;
4600 }
4601
Brandon Jonesd1049182018-03-28 10:02:20 -07004602 SetRobustLengthParam(length, numParams);
4603
Geoff Langc1984ed2016-10-07 12:41:00 -04004604 return true;
4605}
4606
Geoff Langc1984ed2016-10-07 12:41:00 -04004607bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004608 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004609 GLenum pname,
4610 GLsizei bufSize,
4611 GLsizei *length,
4612 GLint *params)
4613{
Brandon Jonesd1049182018-03-28 10:02:20 -07004614
Geoff Langc1984ed2016-10-07 12:41:00 -04004615 if (!ValidateRobustEntryPoint(context, bufSize))
4616 {
4617 return false;
4618 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004619 GLsizei numParams = 0;
4620 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004621 {
4622 return false;
4623 }
4624
Brandon Jonesd1049182018-03-28 10:02:20 -07004625 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004626 {
4627 return false;
4628 }
4629
Brandon Jonesd1049182018-03-28 10:02:20 -07004630 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004631 return true;
4632}
4633
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004634bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4635 TextureType target,
4636 GLenum pname,
4637 GLsizei bufSize,
4638 GLsizei *length,
4639 GLint *params)
4640{
4641 UNIMPLEMENTED();
4642 return false;
4643}
4644
4645bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4646 TextureType target,
4647 GLenum pname,
4648 GLsizei bufSize,
4649 GLsizei *length,
4650 GLuint *params)
4651{
4652 UNIMPLEMENTED();
4653 return false;
4654}
4655
Geoff Langc1984ed2016-10-07 12:41:00 -04004656bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004657 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004658 GLenum pname,
4659 GLsizei bufSize,
4660 const GLfloat *params)
4661{
4662 if (!ValidateRobustEntryPoint(context, bufSize))
4663 {
4664 return false;
4665 }
4666
4667 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4668}
4669
Geoff Langc1984ed2016-10-07 12:41:00 -04004670bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004671 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004672 GLenum pname,
4673 GLsizei bufSize,
4674 const GLint *params)
4675{
4676 if (!ValidateRobustEntryPoint(context, bufSize))
4677 {
4678 return false;
4679 }
4680
4681 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4682}
4683
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004684bool ValidateTexParameterIivRobustANGLE(Context *context,
4685 TextureType target,
4686 GLenum pname,
4687 GLsizei bufSize,
4688 const GLint *params)
4689{
4690 UNIMPLEMENTED();
4691 return false;
4692}
4693
4694bool ValidateTexParameterIuivRobustANGLE(Context *context,
4695 TextureType target,
4696 GLenum pname,
4697 GLsizei bufSize,
4698 const GLuint *params)
4699{
4700 UNIMPLEMENTED();
4701 return false;
4702}
4703
Geoff Langc1984ed2016-10-07 12:41:00 -04004704bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4705 GLuint sampler,
4706 GLenum pname,
4707 GLuint bufSize,
4708 GLsizei *length,
4709 GLfloat *params)
4710{
4711 if (!ValidateRobustEntryPoint(context, bufSize))
4712 {
4713 return false;
4714 }
4715
Brandon Jonesd1049182018-03-28 10:02:20 -07004716 GLsizei numParams = 0;
4717
4718 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004719 {
4720 return false;
4721 }
4722
Brandon Jonesd1049182018-03-28 10:02:20 -07004723 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004724 {
4725 return false;
4726 }
4727
Brandon Jonesd1049182018-03-28 10:02:20 -07004728 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004729 return true;
4730}
4731
Geoff Langc1984ed2016-10-07 12:41:00 -04004732bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4733 GLuint sampler,
4734 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004735 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004736 GLsizei *length,
4737 GLint *params)
4738{
4739 if (!ValidateRobustEntryPoint(context, bufSize))
4740 {
4741 return false;
4742 }
4743
Brandon Jonesd1049182018-03-28 10:02:20 -07004744 GLsizei numParams = 0;
4745
4746 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004747 {
4748 return false;
4749 }
4750
Brandon Jonesd1049182018-03-28 10:02:20 -07004751 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004752 {
4753 return false;
4754 }
4755
Brandon Jonesd1049182018-03-28 10:02:20 -07004756 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004757 return true;
4758}
4759
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004760bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4761 GLuint sampler,
4762 GLenum pname,
4763 GLsizei bufSize,
4764 GLsizei *length,
4765 GLint *params)
4766{
4767 UNIMPLEMENTED();
4768 return false;
4769}
4770
4771bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4772 GLuint sampler,
4773 GLenum pname,
4774 GLsizei bufSize,
4775 GLsizei *length,
4776 GLuint *params)
4777{
4778 UNIMPLEMENTED();
4779 return false;
4780}
4781
Geoff Langc1984ed2016-10-07 12:41:00 -04004782bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4783 GLuint sampler,
4784 GLenum pname,
4785 GLsizei bufSize,
4786 const GLfloat *params)
4787{
4788 if (!ValidateRobustEntryPoint(context, bufSize))
4789 {
4790 return false;
4791 }
4792
4793 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4794}
4795
Geoff Langc1984ed2016-10-07 12:41:00 -04004796bool ValidateSamplerParameterivRobustANGLE(Context *context,
4797 GLuint sampler,
4798 GLenum pname,
4799 GLsizei bufSize,
4800 const GLint *params)
4801{
4802 if (!ValidateRobustEntryPoint(context, bufSize))
4803 {
4804 return false;
4805 }
4806
4807 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4808}
4809
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004810bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4811 GLuint sampler,
4812 GLenum pname,
4813 GLsizei bufSize,
4814 const GLint *param)
4815{
4816 UNIMPLEMENTED();
4817 return false;
4818}
4819
4820bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4821 GLuint sampler,
4822 GLenum pname,
4823 GLsizei bufSize,
4824 const GLuint *param)
4825{
4826 UNIMPLEMENTED();
4827 return false;
4828}
4829
Geoff Lang0b031062016-10-13 14:30:04 -04004830bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4831 GLuint index,
4832 GLenum pname,
4833 GLsizei bufSize,
4834 GLsizei *length,
4835 GLfloat *params)
4836{
4837 if (!ValidateRobustEntryPoint(context, bufSize))
4838 {
4839 return false;
4840 }
4841
Brandon Jonesd1049182018-03-28 10:02:20 -07004842 GLsizei writeLength = 0;
4843
4844 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004845 {
4846 return false;
4847 }
4848
Brandon Jonesd1049182018-03-28 10:02:20 -07004849 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004850 {
4851 return false;
4852 }
4853
Brandon Jonesd1049182018-03-28 10:02:20 -07004854 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004855 return true;
4856}
4857
Geoff Lang0b031062016-10-13 14:30:04 -04004858bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4859 GLuint index,
4860 GLenum pname,
4861 GLsizei bufSize,
4862 GLsizei *length,
4863 GLint *params)
4864{
4865 if (!ValidateRobustEntryPoint(context, bufSize))
4866 {
4867 return false;
4868 }
4869
Brandon Jonesd1049182018-03-28 10:02:20 -07004870 GLsizei writeLength = 0;
4871
4872 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004873 {
4874 return false;
4875 }
4876
Brandon Jonesd1049182018-03-28 10:02:20 -07004877 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004878 {
4879 return false;
4880 }
4881
Brandon Jonesd1049182018-03-28 10:02:20 -07004882 SetRobustLengthParam(length, writeLength);
4883
Geoff Lang0b031062016-10-13 14:30:04 -04004884 return true;
4885}
4886
Geoff Lang0b031062016-10-13 14:30:04 -04004887bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4888 GLuint index,
4889 GLenum pname,
4890 GLsizei bufSize,
4891 GLsizei *length,
4892 void **pointer)
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, true, 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);
4912
Geoff Lang0b031062016-10-13 14:30:04 -04004913 return true;
4914}
4915
Geoff Lang0b031062016-10-13 14:30:04 -04004916bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4917 GLuint index,
4918 GLenum pname,
4919 GLsizei bufSize,
4920 GLsizei *length,
4921 GLint *params)
4922{
4923 if (!ValidateRobustEntryPoint(context, bufSize))
4924 {
4925 return false;
4926 }
4927
Brandon Jonesd1049182018-03-28 10:02:20 -07004928 GLsizei writeLength = 0;
4929
4930 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004931 {
4932 return false;
4933 }
4934
Brandon Jonesd1049182018-03-28 10:02:20 -07004935 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004936 {
4937 return false;
4938 }
4939
Brandon Jonesd1049182018-03-28 10:02:20 -07004940 SetRobustLengthParam(length, writeLength);
4941
Geoff Lang0b031062016-10-13 14:30:04 -04004942 return true;
4943}
4944
Geoff Lang0b031062016-10-13 14:30:04 -04004945bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4946 GLuint index,
4947 GLenum pname,
4948 GLsizei bufSize,
4949 GLsizei *length,
4950 GLuint *params)
4951{
4952 if (!ValidateRobustEntryPoint(context, bufSize))
4953 {
4954 return false;
4955 }
4956
Brandon Jonesd1049182018-03-28 10:02:20 -07004957 GLsizei writeLength = 0;
4958
4959 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004960 {
4961 return false;
4962 }
4963
Brandon Jonesd1049182018-03-28 10:02:20 -07004964 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004965 {
4966 return false;
4967 }
4968
Brandon Jonesd1049182018-03-28 10:02:20 -07004969 SetRobustLengthParam(length, writeLength);
4970
Geoff Lang0b031062016-10-13 14:30:04 -04004971 return true;
4972}
4973
Geoff Lang6899b872016-10-14 11:30:13 -04004974bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4975 GLuint program,
4976 GLuint uniformBlockIndex,
4977 GLenum pname,
4978 GLsizei bufSize,
4979 GLsizei *length,
4980 GLint *params)
4981{
4982 if (!ValidateRobustEntryPoint(context, bufSize))
4983 {
4984 return false;
4985 }
4986
Brandon Jonesd1049182018-03-28 10:02:20 -07004987 GLsizei writeLength = 0;
4988
4989 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4990 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004991 {
4992 return false;
4993 }
4994
Brandon Jonesd1049182018-03-28 10:02:20 -07004995 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004996 {
4997 return false;
4998 }
4999
Brandon Jonesd1049182018-03-28 10:02:20 -07005000 SetRobustLengthParam(length, writeLength);
5001
Geoff Lang6899b872016-10-14 11:30:13 -04005002 return true;
5003}
5004
Brandon Jones416aaf92018-04-10 08:10:16 -07005005bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005006 GLenum target,
5007 GLenum internalformat,
5008 GLenum pname,
5009 GLsizei bufSize,
5010 GLsizei *length,
5011 GLint *params)
5012{
5013 if (!ValidateRobustEntryPoint(context, bufSize))
5014 {
5015 return false;
5016 }
5017
Brandon Jonesd1049182018-03-28 10:02:20 -07005018 GLsizei numParams = 0;
5019
5020 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5021 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005022 {
5023 return false;
5024 }
5025
Brandon Jonesd1049182018-03-28 10:02:20 -07005026 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005027 {
5028 return false;
5029 }
5030
Brandon Jonesd1049182018-03-28 10:02:20 -07005031 SetRobustLengthParam(length, numParams);
5032
Geoff Lang0a9661f2016-10-20 10:59:20 -07005033 return true;
5034}
5035
Jamie Madill5b772312018-03-08 20:28:32 -05005036bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005037 GLuint attribIndex,
5038 GLint size,
5039 GLenum type,
5040 GLboolean pureInteger)
5041{
5042 const Caps &caps = context->getCaps();
5043 if (attribIndex >= caps.maxVertexAttributes)
5044 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005045 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005046 return false;
5047 }
5048
5049 if (size < 1 || size > 4)
5050 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005051 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005052 return false;
Shao80957d92017-02-20 21:25:59 +08005053 }
5054
5055 switch (type)
5056 {
5057 case GL_BYTE:
5058 case GL_UNSIGNED_BYTE:
5059 case GL_SHORT:
5060 case GL_UNSIGNED_SHORT:
5061 break;
5062
5063 case GL_INT:
5064 case GL_UNSIGNED_INT:
5065 if (context->getClientMajorVersion() < 3)
5066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005067 context->handleError(InvalidEnum()
5068 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005069 return false;
5070 }
5071 break;
5072
5073 case GL_FIXED:
5074 case GL_FLOAT:
5075 if (pureInteger)
5076 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005077 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005078 return false;
5079 }
5080 break;
5081
5082 case GL_HALF_FLOAT:
5083 if (context->getClientMajorVersion() < 3)
5084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005085 context->handleError(InvalidEnum()
5086 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005087 return false;
5088 }
5089 if (pureInteger)
5090 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005091 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005092 return false;
5093 }
5094 break;
5095
5096 case GL_INT_2_10_10_10_REV:
5097 case GL_UNSIGNED_INT_2_10_10_10_REV:
5098 if (context->getClientMajorVersion() < 3)
5099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005100 context->handleError(InvalidEnum()
5101 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005102 return false;
5103 }
5104 if (pureInteger)
5105 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005106 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005107 return false;
5108 }
5109 if (size != 4)
5110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005111 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5112 "UNSIGNED_INT_2_10_10_10_REV and "
5113 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005114 return false;
5115 }
5116 break;
5117
5118 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005120 return false;
5121 }
5122
5123 return true;
5124}
5125
Geoff Lang76e65652017-03-27 14:58:02 -04005126// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5127// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5128// specified clear value and the type of a buffer that is being cleared generates an
5129// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005130bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005131 GLint drawbuffer,
5132 const GLenum *validComponentTypes,
5133 size_t validComponentTypeCount)
5134{
5135 const FramebufferAttachment *attachment =
5136 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5137 if (attachment)
5138 {
5139 GLenum componentType = attachment->getFormat().info->componentType;
5140 const GLenum *end = validComponentTypes + validComponentTypeCount;
5141 if (std::find(validComponentTypes, end, componentType) == end)
5142 {
5143 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005144 InvalidOperation()
5145 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005146 return false;
5147 }
5148 }
5149
5150 return true;
5151}
5152
Jamie Madill5b772312018-03-08 20:28:32 -05005153bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005154{
5155 if (!ValidateRobustEntryPoint(context, dataSize))
5156 {
5157 return false;
5158 }
5159
Corentin Wallez336129f2017-10-17 15:55:40 -04005160 gl::Buffer *pixelUnpackBuffer =
5161 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005162 if (pixelUnpackBuffer == nullptr)
5163 {
5164 if (dataSize < imageSize)
5165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005166 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005167 }
5168 }
5169 return true;
5170}
5171
Jamie Madill5b772312018-03-08 20:28:32 -05005172bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005173 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005174 GLenum pname,
5175 bool pointerVersion,
5176 GLsizei *numParams)
5177{
5178 if (numParams)
5179 {
5180 *numParams = 0;
5181 }
5182
Corentin Walleze4477002017-12-01 14:39:58 -05005183 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005184 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005185 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005186 return false;
5187 }
5188
5189 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5190 if (!buffer)
5191 {
5192 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005194 return false;
5195 }
5196
5197 const Extensions &extensions = context->getExtensions();
5198
5199 switch (pname)
5200 {
5201 case GL_BUFFER_USAGE:
5202 case GL_BUFFER_SIZE:
5203 break;
5204
5205 case GL_BUFFER_ACCESS_OES:
5206 if (!extensions.mapBuffer)
5207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005208 context->handleError(InvalidEnum()
5209 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005210 return false;
5211 }
5212 break;
5213
5214 case GL_BUFFER_MAPPED:
5215 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5216 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5217 !extensions.mapBufferRange)
5218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005219 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5220 "GL_OES_mapbuffer or "
5221 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 return false;
5223 }
5224 break;
5225
5226 case GL_BUFFER_MAP_POINTER:
5227 if (!pointerVersion)
5228 {
5229 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005230 InvalidEnum()
5231 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005232 return false;
5233 }
5234 break;
5235
5236 case GL_BUFFER_ACCESS_FLAGS:
5237 case GL_BUFFER_MAP_OFFSET:
5238 case GL_BUFFER_MAP_LENGTH:
5239 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005241 context->handleError(InvalidEnum()
5242 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005243 return false;
5244 }
5245 break;
5246
5247 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005248 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005249 return false;
5250 }
5251
5252 // All buffer parameter queries return one value.
5253 if (numParams)
5254 {
5255 *numParams = 1;
5256 }
5257
5258 return true;
5259}
5260
5261bool ValidateGetRenderbufferParameterivBase(Context *context,
5262 GLenum target,
5263 GLenum pname,
5264 GLsizei *length)
5265{
5266 if (length)
5267 {
5268 *length = 0;
5269 }
5270
5271 if (target != GL_RENDERBUFFER)
5272 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005273 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005274 return false;
5275 }
5276
5277 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5278 if (renderbuffer == nullptr)
5279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005281 return false;
5282 }
5283
5284 switch (pname)
5285 {
5286 case GL_RENDERBUFFER_WIDTH:
5287 case GL_RENDERBUFFER_HEIGHT:
5288 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5289 case GL_RENDERBUFFER_RED_SIZE:
5290 case GL_RENDERBUFFER_GREEN_SIZE:
5291 case GL_RENDERBUFFER_BLUE_SIZE:
5292 case GL_RENDERBUFFER_ALPHA_SIZE:
5293 case GL_RENDERBUFFER_DEPTH_SIZE:
5294 case GL_RENDERBUFFER_STENCIL_SIZE:
5295 break;
5296
5297 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5298 if (!context->getExtensions().framebufferMultisample)
5299 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005300 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005301 return false;
5302 }
5303 break;
5304
5305 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005306 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005307 return false;
5308 }
5309
5310 if (length)
5311 {
5312 *length = 1;
5313 }
5314 return true;
5315}
5316
5317bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5318{
5319 if (length)
5320 {
5321 *length = 0;
5322 }
5323
5324 if (GetValidShader(context, shader) == nullptr)
5325 {
5326 return false;
5327 }
5328
5329 switch (pname)
5330 {
5331 case GL_SHADER_TYPE:
5332 case GL_DELETE_STATUS:
5333 case GL_COMPILE_STATUS:
5334 case GL_INFO_LOG_LENGTH:
5335 case GL_SHADER_SOURCE_LENGTH:
5336 break;
5337
5338 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5339 if (!context->getExtensions().translatedShaderSource)
5340 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005341 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005342 return false;
5343 }
5344 break;
5345
5346 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005347 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005348 return false;
5349 }
5350
5351 if (length)
5352 {
5353 *length = 1;
5354 }
5355 return true;
5356}
5357
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005358bool ValidateGetTexParameterBase(Context *context,
5359 TextureType target,
5360 GLenum pname,
5361 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005362{
5363 if (length)
5364 {
5365 *length = 0;
5366 }
5367
5368 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5369 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005370 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005371 return false;
5372 }
5373
5374 if (context->getTargetTexture(target) == nullptr)
5375 {
5376 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 return false;
5379 }
5380
5381 switch (pname)
5382 {
5383 case GL_TEXTURE_MAG_FILTER:
5384 case GL_TEXTURE_MIN_FILTER:
5385 case GL_TEXTURE_WRAP_S:
5386 case GL_TEXTURE_WRAP_T:
5387 break;
5388
5389 case GL_TEXTURE_USAGE_ANGLE:
5390 if (!context->getExtensions().textureUsage)
5391 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395 break;
5396
5397 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005398 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005399 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005400 return false;
5401 }
5402 break;
5403
5404 case GL_TEXTURE_IMMUTABLE_FORMAT:
5405 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5406 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005408 return false;
5409 }
5410 break;
5411
5412 case GL_TEXTURE_WRAP_R:
5413 case GL_TEXTURE_IMMUTABLE_LEVELS:
5414 case GL_TEXTURE_SWIZZLE_R:
5415 case GL_TEXTURE_SWIZZLE_G:
5416 case GL_TEXTURE_SWIZZLE_B:
5417 case GL_TEXTURE_SWIZZLE_A:
5418 case GL_TEXTURE_BASE_LEVEL:
5419 case GL_TEXTURE_MAX_LEVEL:
5420 case GL_TEXTURE_MIN_LOD:
5421 case GL_TEXTURE_MAX_LOD:
5422 case GL_TEXTURE_COMPARE_MODE:
5423 case GL_TEXTURE_COMPARE_FUNC:
5424 if (context->getClientMajorVersion() < 3)
5425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005426 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005427 return false;
5428 }
5429 break;
5430
5431 case GL_TEXTURE_SRGB_DECODE_EXT:
5432 if (!context->getExtensions().textureSRGBDecode)
5433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005434 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005435 return false;
5436 }
5437 break;
5438
Yunchao Hebacaa712018-01-30 14:01:39 +08005439 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5440 if (context->getClientVersion() < Version(3, 1))
5441 {
5442 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5443 return false;
5444 }
5445 break;
5446
Jamie Madillbe849e42017-05-02 15:49:00 -04005447 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005448 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005449 return false;
5450 }
5451
5452 if (length)
5453 {
5454 *length = 1;
5455 }
5456 return true;
5457}
5458
5459bool ValidateGetVertexAttribBase(Context *context,
5460 GLuint index,
5461 GLenum pname,
5462 GLsizei *length,
5463 bool pointer,
5464 bool pureIntegerEntryPoint)
5465{
5466 if (length)
5467 {
5468 *length = 0;
5469 }
5470
5471 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005473 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005474 return false;
5475 }
5476
5477 if (index >= context->getCaps().maxVertexAttributes)
5478 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005479 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005480 return false;
5481 }
5482
5483 if (pointer)
5484 {
5485 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5486 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005487 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005488 return false;
5489 }
5490 }
5491 else
5492 {
5493 switch (pname)
5494 {
5495 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5496 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5497 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5498 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5499 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5500 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5501 case GL_CURRENT_VERTEX_ATTRIB:
5502 break;
5503
5504 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5505 static_assert(
5506 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5507 "ANGLE extension enums not equal to GL enums.");
5508 if (context->getClientMajorVersion() < 3 &&
5509 !context->getExtensions().instancedArrays)
5510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005511 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5512 "requires OpenGL ES 3.0 or "
5513 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005514 return false;
5515 }
5516 break;
5517
5518 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5519 if (context->getClientMajorVersion() < 3)
5520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005521 context->handleError(
5522 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005523 return false;
5524 }
5525 break;
5526
5527 case GL_VERTEX_ATTRIB_BINDING:
5528 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5529 if (context->getClientVersion() < ES_3_1)
5530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005531 context->handleError(InvalidEnum()
5532 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005533 return false;
5534 }
5535 break;
5536
5537 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005538 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005539 return false;
5540 }
5541 }
5542
5543 if (length)
5544 {
5545 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5546 {
5547 *length = 4;
5548 }
5549 else
5550 {
5551 *length = 1;
5552 }
5553 }
5554
5555 return true;
5556}
5557
Jamie Madill4928b7c2017-06-20 12:57:39 -04005558bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005559 GLint x,
5560 GLint y,
5561 GLsizei width,
5562 GLsizei height,
5563 GLenum format,
5564 GLenum type,
5565 GLsizei bufSize,
5566 GLsizei *length,
5567 GLsizei *columns,
5568 GLsizei *rows,
5569 void *pixels)
5570{
5571 if (length != nullptr)
5572 {
5573 *length = 0;
5574 }
5575 if (rows != nullptr)
5576 {
5577 *rows = 0;
5578 }
5579 if (columns != nullptr)
5580 {
5581 *columns = 0;
5582 }
5583
5584 if (width < 0 || height < 0)
5585 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005586 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005587 return false;
5588 }
5589
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005590 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005591
Jamie Madill427064d2018-04-13 16:20:34 -04005592 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005593 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005594 return false;
5595 }
5596
Jamie Madille98b1b52018-03-08 09:47:23 -05005597 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005598 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005599 return false;
5600 }
5601
Jamie Madill690c8eb2018-03-12 15:20:03 -04005602 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005603 ASSERT(framebuffer);
5604
5605 if (framebuffer->getReadBufferState() == GL_NONE)
5606 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005607 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005608 return false;
5609 }
5610
5611 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5612 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5613 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5614 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5615 // situation is an application error that would lead to a crash in ANGLE.
5616 if (readBuffer == nullptr)
5617 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005618 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005619 return false;
5620 }
5621
Martin Radev28031682017-07-28 14:47:56 +03005622 // ANGLE_multiview, Revision 1:
5623 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5624 // current read framebuffer is not NONE.
5625 if (readBuffer->getMultiviewLayout() != GL_NONE)
5626 {
5627 context->handleError(InvalidFramebufferOperation()
5628 << "Attempting to read from a multi-view framebuffer.");
5629 return false;
5630 }
5631
Geoff Lang280ba992017-04-18 16:30:58 -04005632 if (context->getExtensions().webglCompatibility)
5633 {
5634 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5635 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5636 // and type before validating the combination of format and type. However, the
5637 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5638 // verifies that GL_INVALID_OPERATION is generated.
5639 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5640 // dEQP/WebGL.
5641 if (!ValidReadPixelsFormatEnum(context, format))
5642 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005643 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005644 return false;
5645 }
5646
5647 if (!ValidReadPixelsTypeEnum(context, type))
5648 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005649 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005650 return false;
5651 }
5652 }
5653
Jamie Madill690c8eb2018-03-12 15:20:03 -04005654 GLenum currentFormat = GL_NONE;
5655 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5656
5657 GLenum currentType = GL_NONE;
5658 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5659
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5661
5662 bool validFormatTypeCombination =
5663 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5664
5665 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5666 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005668 return false;
5669 }
5670
5671 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005672 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005673 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5674 {
5675 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005676 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005677 return false;
5678 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005679 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5680 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5681 {
5682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5683 return false;
5684 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005685
5686 // .. the data would be packed to the buffer object such that the memory writes required
5687 // would exceed the data store size.
5688 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5689 const gl::Extents size(width, height, 1);
5690 const auto &pack = context->getGLState().getPackState();
5691
5692 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5693 if (endByteOrErr.isError())
5694 {
5695 context->handleError(endByteOrErr.getError());
5696 return false;
5697 }
5698
5699 size_t endByte = endByteOrErr.getResult();
5700 if (bufSize >= 0)
5701 {
5702 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5703 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005704 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005705 return false;
5706 }
5707 }
5708
5709 if (pixelPackBuffer != nullptr)
5710 {
5711 CheckedNumeric<size_t> checkedEndByte(endByte);
5712 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5713 checkedEndByte += checkedOffset;
5714
5715 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5716 {
5717 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005719 return false;
5720 }
5721 }
5722
5723 if (pixelPackBuffer == nullptr && length != nullptr)
5724 {
5725 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5726 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005727 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005728 return false;
5729 }
5730
5731 *length = static_cast<GLsizei>(endByte);
5732 }
5733
Geoff Langa953b522018-02-21 16:56:23 -05005734 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005735 angle::CheckedNumeric<int> clippedExtent(length);
5736 if (start < 0)
5737 {
5738 // "subtract" the area that is less than 0
5739 clippedExtent += start;
5740 }
5741
Geoff Langa953b522018-02-21 16:56:23 -05005742 angle::CheckedNumeric<int> readExtent = start;
5743 readExtent += length;
5744 if (!readExtent.IsValid())
5745 {
5746 return false;
5747 }
5748
5749 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005750 {
5751 // Subtract the region to the right of the read buffer
5752 clippedExtent -= (readExtent - bufferSize);
5753 }
5754
5755 if (!clippedExtent.IsValid())
5756 {
Geoff Langa953b522018-02-21 16:56:23 -05005757 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005758 }
5759
Geoff Langa953b522018-02-21 16:56:23 -05005760 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5761 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005762 };
5763
Geoff Langa953b522018-02-21 16:56:23 -05005764 GLsizei writtenColumns = 0;
5765 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5766 {
5767 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5768 return false;
5769 }
5770
5771 GLsizei writtenRows = 0;
5772 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5773 {
5774 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5775 return false;
5776 }
5777
Jamie Madillbe849e42017-05-02 15:49:00 -04005778 if (columns != nullptr)
5779 {
Geoff Langa953b522018-02-21 16:56:23 -05005780 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005781 }
5782
5783 if (rows != nullptr)
5784 {
Geoff Langa953b522018-02-21 16:56:23 -05005785 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005786 }
5787
5788 return true;
5789}
5790
5791template <typename ParamType>
5792bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005793 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005794 GLenum pname,
5795 GLsizei bufSize,
5796 const ParamType *params)
5797{
5798 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5799 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005800 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 return false;
5802 }
5803
5804 if (context->getTargetTexture(target) == nullptr)
5805 {
5806 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005807 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005808 return false;
5809 }
5810
5811 const GLsizei minBufSize = 1;
5812 if (bufSize >= 0 && bufSize < minBufSize)
5813 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005814 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 return false;
5816 }
5817
5818 switch (pname)
5819 {
5820 case GL_TEXTURE_WRAP_R:
5821 case GL_TEXTURE_SWIZZLE_R:
5822 case GL_TEXTURE_SWIZZLE_G:
5823 case GL_TEXTURE_SWIZZLE_B:
5824 case GL_TEXTURE_SWIZZLE_A:
5825 case GL_TEXTURE_BASE_LEVEL:
5826 case GL_TEXTURE_MAX_LEVEL:
5827 case GL_TEXTURE_COMPARE_MODE:
5828 case GL_TEXTURE_COMPARE_FUNC:
5829 case GL_TEXTURE_MIN_LOD:
5830 case GL_TEXTURE_MAX_LOD:
5831 if (context->getClientMajorVersion() < 3)
5832 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005833 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005834 return false;
5835 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005836 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005838 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5839 "available without "
5840 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005841 return false;
5842 }
5843 break;
5844
5845 default:
5846 break;
5847 }
5848
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005849 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005850 {
5851 switch (pname)
5852 {
5853 case GL_TEXTURE_MIN_FILTER:
5854 case GL_TEXTURE_MAG_FILTER:
5855 case GL_TEXTURE_WRAP_S:
5856 case GL_TEXTURE_WRAP_T:
5857 case GL_TEXTURE_WRAP_R:
5858 case GL_TEXTURE_MIN_LOD:
5859 case GL_TEXTURE_MAX_LOD:
5860 case GL_TEXTURE_COMPARE_MODE:
5861 case GL_TEXTURE_COMPARE_FUNC:
5862 context->handleError(InvalidEnum()
5863 << "Invalid parameter for 2D multisampled textures.");
5864 return false;
5865 }
5866 }
5867
Jamie Madillbe849e42017-05-02 15:49:00 -04005868 switch (pname)
5869 {
5870 case GL_TEXTURE_WRAP_S:
5871 case GL_TEXTURE_WRAP_T:
5872 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005873 {
5874 bool restrictedWrapModes =
5875 target == TextureType::External || target == TextureType::Rectangle;
5876 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005877 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005878 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005879 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005880 }
5881 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005882
5883 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005884 {
5885 bool restrictedMinFilter =
5886 target == TextureType::External || target == TextureType::Rectangle;
5887 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005888 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005889 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005890 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005891 }
5892 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005893
5894 case GL_TEXTURE_MAG_FILTER:
5895 if (!ValidateTextureMagFilterValue(context, params))
5896 {
5897 return false;
5898 }
5899 break;
5900
5901 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005902 if (!context->getExtensions().textureUsage)
5903 {
5904 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5905 return false;
5906 }
5907
Jamie Madillbe849e42017-05-02 15:49:00 -04005908 switch (ConvertToGLenum(params[0]))
5909 {
5910 case GL_NONE:
5911 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5912 break;
5913
5914 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005916 return false;
5917 }
5918 break;
5919
5920 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005921 {
5922 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5923 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005924 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005925 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005926 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005927 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5928 }
5929 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005930
5931 case GL_TEXTURE_MIN_LOD:
5932 case GL_TEXTURE_MAX_LOD:
5933 // any value is permissible
5934 break;
5935
5936 case GL_TEXTURE_COMPARE_MODE:
5937 if (!ValidateTextureCompareModeValue(context, params))
5938 {
5939 return false;
5940 }
5941 break;
5942
5943 case GL_TEXTURE_COMPARE_FUNC:
5944 if (!ValidateTextureCompareFuncValue(context, params))
5945 {
5946 return false;
5947 }
5948 break;
5949
5950 case GL_TEXTURE_SWIZZLE_R:
5951 case GL_TEXTURE_SWIZZLE_G:
5952 case GL_TEXTURE_SWIZZLE_B:
5953 case GL_TEXTURE_SWIZZLE_A:
5954 switch (ConvertToGLenum(params[0]))
5955 {
5956 case GL_RED:
5957 case GL_GREEN:
5958 case GL_BLUE:
5959 case GL_ALPHA:
5960 case GL_ZERO:
5961 case GL_ONE:
5962 break;
5963
5964 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005965 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005966 return false;
5967 }
5968 break;
5969
5970 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005971 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005973 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005974 return false;
5975 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005976 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005978 context->handleError(InvalidOperation()
5979 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005980 return false;
5981 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005982 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005983 {
5984 context->handleError(InvalidOperation()
5985 << "Base level must be 0 for multisampled textures.");
5986 return false;
5987 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005988 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005989 {
5990 context->handleError(InvalidOperation()
5991 << "Base level must be 0 for rectangle textures.");
5992 return false;
5993 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005994 break;
5995
5996 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005997 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005998 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005999 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006000 return false;
6001 }
6002 break;
6003
6004 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6005 if (context->getClientVersion() < Version(3, 1))
6006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006007 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006008 return false;
6009 }
6010 switch (ConvertToGLenum(params[0]))
6011 {
6012 case GL_DEPTH_COMPONENT:
6013 case GL_STENCIL_INDEX:
6014 break;
6015
6016 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006017 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006018 return false;
6019 }
6020 break;
6021
6022 case GL_TEXTURE_SRGB_DECODE_EXT:
6023 if (!ValidateTextureSRGBDecodeValue(context, params))
6024 {
6025 return false;
6026 }
6027 break;
6028
6029 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006030 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006031 return false;
6032 }
6033
6034 return true;
6035}
6036
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006037template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6038template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006039
Jamie Madill5b772312018-03-08 20:28:32 -05006040bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006041{
6042 if (index >= MAX_VERTEX_ATTRIBS)
6043 {
6044 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6045 return false;
6046 }
6047
6048 return true;
6049}
6050
6051bool ValidateGetActiveUniformBlockivBase(Context *context,
6052 GLuint program,
6053 GLuint uniformBlockIndex,
6054 GLenum pname,
6055 GLsizei *length)
6056{
6057 if (length)
6058 {
6059 *length = 0;
6060 }
6061
6062 if (context->getClientMajorVersion() < 3)
6063 {
6064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6065 return false;
6066 }
6067
6068 Program *programObject = GetValidProgram(context, program);
6069 if (!programObject)
6070 {
6071 return false;
6072 }
6073
6074 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6075 {
6076 context->handleError(InvalidValue()
6077 << "uniformBlockIndex exceeds active uniform block count.");
6078 return false;
6079 }
6080
6081 switch (pname)
6082 {
6083 case GL_UNIFORM_BLOCK_BINDING:
6084 case GL_UNIFORM_BLOCK_DATA_SIZE:
6085 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6086 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6087 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6088 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6089 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6090 break;
6091
6092 default:
6093 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6094 return false;
6095 }
6096
6097 if (length)
6098 {
6099 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6100 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006101 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006102 programObject->getUniformBlockByIndex(uniformBlockIndex);
6103 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6104 }
6105 else
6106 {
6107 *length = 1;
6108 }
6109 }
6110
6111 return true;
6112}
6113
Jamie Madill9696d072017-08-26 23:19:57 -04006114template <typename ParamType>
6115bool ValidateSamplerParameterBase(Context *context,
6116 GLuint sampler,
6117 GLenum pname,
6118 GLsizei bufSize,
6119 ParamType *params)
6120{
6121 if (context->getClientMajorVersion() < 3)
6122 {
6123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6124 return false;
6125 }
6126
6127 if (!context->isSampler(sampler))
6128 {
6129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6130 return false;
6131 }
6132
6133 const GLsizei minBufSize = 1;
6134 if (bufSize >= 0 && bufSize < minBufSize)
6135 {
6136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6137 return false;
6138 }
6139
6140 switch (pname)
6141 {
6142 case GL_TEXTURE_WRAP_S:
6143 case GL_TEXTURE_WRAP_T:
6144 case GL_TEXTURE_WRAP_R:
6145 if (!ValidateTextureWrapModeValue(context, params, false))
6146 {
6147 return false;
6148 }
6149 break;
6150
6151 case GL_TEXTURE_MIN_FILTER:
6152 if (!ValidateTextureMinFilterValue(context, params, false))
6153 {
6154 return false;
6155 }
6156 break;
6157
6158 case GL_TEXTURE_MAG_FILTER:
6159 if (!ValidateTextureMagFilterValue(context, params))
6160 {
6161 return false;
6162 }
6163 break;
6164
6165 case GL_TEXTURE_MIN_LOD:
6166 case GL_TEXTURE_MAX_LOD:
6167 // any value is permissible
6168 break;
6169
6170 case GL_TEXTURE_COMPARE_MODE:
6171 if (!ValidateTextureCompareModeValue(context, params))
6172 {
6173 return false;
6174 }
6175 break;
6176
6177 case GL_TEXTURE_COMPARE_FUNC:
6178 if (!ValidateTextureCompareFuncValue(context, params))
6179 {
6180 return false;
6181 }
6182 break;
6183
6184 case GL_TEXTURE_SRGB_DECODE_EXT:
6185 if (!ValidateTextureSRGBDecodeValue(context, params))
6186 {
6187 return false;
6188 }
6189 break;
6190
Luc Ferron1b1a8642018-01-23 15:12:01 -05006191 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6192 {
6193 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6194 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6195 {
6196 return false;
6197 }
6198 }
6199 break;
6200
Jamie Madill9696d072017-08-26 23:19:57 -04006201 default:
6202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6203 return false;
6204 }
6205
6206 return true;
6207}
6208
6209template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6210template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6211
6212bool ValidateGetSamplerParameterBase(Context *context,
6213 GLuint sampler,
6214 GLenum pname,
6215 GLsizei *length)
6216{
6217 if (length)
6218 {
6219 *length = 0;
6220 }
6221
6222 if (context->getClientMajorVersion() < 3)
6223 {
6224 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6225 return false;
6226 }
6227
6228 if (!context->isSampler(sampler))
6229 {
6230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6231 return false;
6232 }
6233
6234 switch (pname)
6235 {
6236 case GL_TEXTURE_WRAP_S:
6237 case GL_TEXTURE_WRAP_T:
6238 case GL_TEXTURE_WRAP_R:
6239 case GL_TEXTURE_MIN_FILTER:
6240 case GL_TEXTURE_MAG_FILTER:
6241 case GL_TEXTURE_MIN_LOD:
6242 case GL_TEXTURE_MAX_LOD:
6243 case GL_TEXTURE_COMPARE_MODE:
6244 case GL_TEXTURE_COMPARE_FUNC:
6245 break;
6246
Luc Ferron1b1a8642018-01-23 15:12:01 -05006247 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6248 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6249 {
6250 return false;
6251 }
6252 break;
6253
Jamie Madill9696d072017-08-26 23:19:57 -04006254 case GL_TEXTURE_SRGB_DECODE_EXT:
6255 if (!context->getExtensions().textureSRGBDecode)
6256 {
6257 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6258 return false;
6259 }
6260 break;
6261
6262 default:
6263 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6264 return false;
6265 }
6266
6267 if (length)
6268 {
6269 *length = 1;
6270 }
6271 return true;
6272}
6273
6274bool ValidateGetInternalFormativBase(Context *context,
6275 GLenum target,
6276 GLenum internalformat,
6277 GLenum pname,
6278 GLsizei bufSize,
6279 GLsizei *numParams)
6280{
6281 if (numParams)
6282 {
6283 *numParams = 0;
6284 }
6285
6286 if (context->getClientMajorVersion() < 3)
6287 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006288 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006289 return false;
6290 }
6291
6292 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6293 if (!formatCaps.renderable)
6294 {
6295 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6296 return false;
6297 }
6298
6299 switch (target)
6300 {
6301 case GL_RENDERBUFFER:
6302 break;
6303
6304 case GL_TEXTURE_2D_MULTISAMPLE:
6305 if (context->getClientVersion() < ES_3_1)
6306 {
6307 context->handleError(InvalidOperation()
6308 << "Texture target requires at least OpenGL ES 3.1.");
6309 return false;
6310 }
6311 break;
6312
6313 default:
6314 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6315 return false;
6316 }
6317
6318 if (bufSize < 0)
6319 {
6320 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6321 return false;
6322 }
6323
6324 GLsizei maxWriteParams = 0;
6325 switch (pname)
6326 {
6327 case GL_NUM_SAMPLE_COUNTS:
6328 maxWriteParams = 1;
6329 break;
6330
6331 case GL_SAMPLES:
6332 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6333 break;
6334
6335 default:
6336 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6337 return false;
6338 }
6339
6340 if (numParams)
6341 {
6342 // glGetInternalFormativ will not overflow bufSize
6343 *numParams = std::min(bufSize, maxWriteParams);
6344 }
6345
6346 return true;
6347}
6348
Jamie Madille98b1b52018-03-08 09:47:23 -05006349bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6350{
Jamie Madill427064d2018-04-13 16:20:34 -04006351 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006352 {
6353 context->handleError(InvalidOperation());
6354 return false;
6355 }
6356 return true;
6357}
6358
Lingfeng Yang038dd532018-03-29 17:31:52 -07006359bool ValidateMultitextureUnit(Context *context, GLenum texture)
6360{
6361 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6362 {
6363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6364 return false;
6365 }
6366 return true;
6367}
6368
Jamie Madillc29968b2016-01-20 11:17:23 -05006369} // namespace gl