blob: 87fd971248b4803c840a82293ee7ccc70d9ff724 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Lingfeng Yangf97641c2018-06-21 19:22:45 -070025#include "libANGLE/queryutils.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040026#include "libANGLE/validationES2.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29#include "common/mathutil.h"
30#include "common/utilities.h"
31
Jamie Madille2e406c2016-06-02 13:04:10 -040032using namespace angle;
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034namespace gl
35{
Jamie Madill1ca74672015-07-21 15:14:11 -040036namespace
37{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050038bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
39{
40 // List of compressed format that require that the texture size is smaller than or a multiple of
41 // the compressed block size.
42 switch (internalFormat)
43 {
44 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
46 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
47 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
48 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
52 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
53 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59 return true;
jchen10a99ed552017-09-22 08:10:32 +080060
Luc Ferron9dbaeba2018-02-01 07:26:59 -050061 default:
62 return false;
63 }
64}
65bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
66{
67 // Compressed sub textures have additional formats that requires exact size.
68 // ES 3.1, Section 8.7, Page 171
69 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
70 IsETC2EACFormat(internalFormat);
71}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030072
73bool DifferenceCanOverflow(GLint a, GLint b)
74{
75 CheckedNumeric<GLint> checkedA(a);
76 checkedA -= b;
77 // Use negation to make sure that the difference can't overflow regardless of the order.
78 checkedA = -checkedA;
79 return !checkedA.IsValid();
80}
81
Jamie Madillac43aaa2018-07-31 11:22:13 -040082bool ValidateDrawClientAttribs(Context *context)
83{
84 if (!context->getStateCache().hasAnyEnabledClientAttrib())
85 return true;
86
87 const gl::State &state = context->getGLState();
88
89 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
90 {
91 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
92 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
93 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
94 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
95 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
96 return false;
97 }
98
99 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
100 {
101 // This is an application error that would normally result in a crash, but we catch it
102 // and return an error
103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
104 return false;
105 }
106
107 return true;
108}
109
Jamie Madill5b772312018-03-08 20:28:32 -0500110bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -0400111{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700112 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -0400113 const gl::Program *program = state.getProgram();
114
Jamie Madillac43aaa2018-07-31 11:22:13 -0400115 if (!ValidateDrawClientAttribs(context))
Jamie Madill51af38b2018-04-15 08:50:56 -0400116 {
Jamie Madillac43aaa2018-07-31 11:22:13 -0400117 return false;
Jamie Madill51af38b2018-04-15 08:50:56 -0400118 }
119
120 // If we're drawing zero vertices, we have enough data.
121 if (vertexCount <= 0 || primcount <= 0)
122 {
123 return true;
124 }
125
Jamie Madillac43aaa2018-07-31 11:22:13 -0400126 const VertexArray *vao = state.getVertexArray();
Jamie Madill231c7f52017-04-26 13:45:37 -0400127 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800128 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill51af38b2018-04-15 08:50:56 -0400129
Jamie Madilldc358af2018-07-31 11:22:13 -0400130 const AttributesMask &activeAttribs = context->getStateCache().getActiveBufferedAttribsMask();
Jamie Madill51af38b2018-04-15 08:50:56 -0400131
132 for (size_t attributeIndex : activeAttribs)
Jamie Madill1ca74672015-07-21 15:14:11 -0400133 {
134 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400135 ASSERT(attrib.enabled);
Corentin Wallez672f7f32017-06-15 17:42:17 -0400136
Lingfeng Yang038dd532018-03-29 17:31:52 -0700137 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Jamie Madill2eb65032018-07-30 10:25:57 -0400138 ASSERT(context->isGLES1() || program->isAttribLocationActive(attributeIndex));
Corentin Wallezfd456442016-12-21 17:57:00 -0500139
Jamie Madill02c9c042018-04-17 13:43:48 -0400140 GLint maxVertexElement = maxVertex;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300141 GLuint divisor = binding.getDivisor();
Jamie Madill02c9c042018-04-17 13:43:48 -0400142 if (divisor != 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500143 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300144 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500145 }
146
147 // We do manual overflow checks here instead of using safe_math.h because it was
148 // a bottleneck. Thanks to some properties of GL we know inequalities that can
149 // help us make the overflow checks faster.
150
151 // The max possible attribSize is 16 for a vector of 4 32 bit values.
152 constexpr uint64_t kMaxAttribSize = 16;
153 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
154 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
155
156 // We know attribStride is given as a GLsizei which is typedefed to int.
157 // We also know an upper bound for attribSize.
Jamie Madill02c9c042018-04-17 13:43:48 -0400158 static_assert(std::is_same<int, GLsizei>::value, "Unexpected type");
159 ASSERT(ComputeVertexAttributeStride(attrib, binding) == binding.getStride());
160 uint64_t attribStride = binding.getStride();
161 ASSERT(attribStride <= kIntMax && ComputeVertexAttributeTypeSize(attrib) <= kMaxAttribSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500162
Jamie Madill02c9c042018-04-17 13:43:48 -0400163 // Computing the product of two 32-bit ints will fit in 64 bits without overflow.
164 static_assert(kIntMax * kIntMax < kUint64Max, "Unexpected overflow");
165 uint64_t attribDataSizeMinusAttribSize = maxVertexElement * attribStride;
Corentin Wallezfd456442016-12-21 17:57:00 -0500166
167 // An overflow can happen when adding the offset, check for it.
Jamie Madill02c9c042018-04-17 13:43:48 -0400168 if (attribDataSizeMinusAttribSize > kUint64Max - attrib.cachedSizePlusRelativeOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500169 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500171 return false;
172 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500173
174 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
Jamie Madill02c9c042018-04-17 13:43:48 -0400175 // We can return INVALID_OPERATION if our array buffer does not have enough backing data.
176 if (attribDataSizeMinusAttribSize + attrib.cachedSizePlusRelativeOffset >
177 binding.getCachedBufferSizeMinusOffset())
Corentin Wallezfd456442016-12-21 17:57:00 -0500178 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500180 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400181 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400182 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800183
Jamie Madill1ca74672015-07-21 15:14:11 -0400184 return true;
185}
186
Jamie Madill5b772312018-03-08 20:28:32 -0500187bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400188{
189 switch (type)
190 {
191 // Types referenced in Table 3.4 of the ES 2.0.25 spec
192 case GL_UNSIGNED_BYTE:
193 case GL_UNSIGNED_SHORT_4_4_4_4:
194 case GL_UNSIGNED_SHORT_5_5_5_1:
195 case GL_UNSIGNED_SHORT_5_6_5:
196 return context->getClientVersion() >= ES_2_0;
197
198 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
199 case GL_BYTE:
200 case GL_INT:
201 case GL_SHORT:
202 case GL_UNSIGNED_INT:
203 case GL_UNSIGNED_INT_10F_11F_11F_REV:
204 case GL_UNSIGNED_INT_24_8:
205 case GL_UNSIGNED_INT_2_10_10_10_REV:
206 case GL_UNSIGNED_INT_5_9_9_9_REV:
207 case GL_UNSIGNED_SHORT:
208 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
209 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
210 return context->getClientVersion() >= ES_3_0;
211
212 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400213 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
214 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400215
216 case GL_HALF_FLOAT:
217 return context->getClientVersion() >= ES_3_0 ||
218 context->getExtensions().textureHalfFloat;
219
220 case GL_HALF_FLOAT_OES:
221 return context->getExtensions().colorBufferHalfFloat;
222
223 default:
224 return false;
225 }
226}
227
Jamie Madill5b772312018-03-08 20:28:32 -0500228bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400229{
230 switch (format)
231 {
232 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
233 case GL_RGBA:
234 case GL_RGB:
235 case GL_ALPHA:
236 return context->getClientVersion() >= ES_2_0;
237
238 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
239 case GL_RG:
240 case GL_RED:
241 case GL_RGBA_INTEGER:
242 case GL_RGB_INTEGER:
243 case GL_RG_INTEGER:
244 case GL_RED_INTEGER:
245 return context->getClientVersion() >= ES_3_0;
246
247 case GL_SRGB_ALPHA_EXT:
248 case GL_SRGB_EXT:
249 return context->getExtensions().sRGB;
250
251 case GL_BGRA_EXT:
252 return context->getExtensions().readFormatBGRA;
253
254 default:
255 return false;
256 }
257}
258
Jamie Madill5b772312018-03-08 20:28:32 -0500259bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400260 GLenum framebufferComponentType,
261 GLenum format,
262 GLenum type)
263{
264 switch (framebufferComponentType)
265 {
266 case GL_UNSIGNED_NORMALIZED:
267 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
268 // ReadPixels with BGRA even if the extension is not present
269 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
270 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
271 type == GL_UNSIGNED_BYTE);
272
273 case GL_SIGNED_NORMALIZED:
274 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
275
276 case GL_INT:
277 return (format == GL_RGBA_INTEGER && type == GL_INT);
278
279 case GL_UNSIGNED_INT:
280 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
281
282 case GL_FLOAT:
283 return (format == GL_RGBA && type == GL_FLOAT);
284
285 default:
286 UNREACHABLE();
287 return false;
288 }
289}
290
Geoff Langc1984ed2016-10-07 12:41:00 -0400291template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400292bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400293{
294 switch (ConvertToGLenum(params[0]))
295 {
296 case GL_CLAMP_TO_EDGE:
297 break;
298
299 case GL_REPEAT:
300 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400301 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400302 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400303 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700304 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 return false;
306 }
307 break;
308
309 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700310 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400311 return false;
312 }
313
314 return true;
315}
316
317template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400318bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400319{
320 switch (ConvertToGLenum(params[0]))
321 {
322 case GL_NEAREST:
323 case GL_LINEAR:
324 break;
325
326 case GL_NEAREST_MIPMAP_NEAREST:
327 case GL_LINEAR_MIPMAP_NEAREST:
328 case GL_NEAREST_MIPMAP_LINEAR:
329 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400330 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400331 {
332 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700333 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400334 return false;
335 }
336 break;
337
338 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400340 return false;
341 }
342
343 return true;
344}
345
346template <typename ParamType>
347bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
348{
349 switch (ConvertToGLenum(params[0]))
350 {
351 case GL_NEAREST:
352 case GL_LINEAR:
353 break;
354
355 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700356 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400357 return false;
358 }
359
360 return true;
361}
362
363template <typename ParamType>
364bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
365{
366 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
367 switch (ConvertToGLenum(params[0]))
368 {
369 case GL_NONE:
370 case GL_COMPARE_REF_TO_TEXTURE:
371 break;
372
373 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400375 return false;
376 }
377
378 return true;
379}
380
381template <typename ParamType>
382bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
383{
384 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
385 switch (ConvertToGLenum(params[0]))
386 {
387 case GL_LEQUAL:
388 case GL_GEQUAL:
389 case GL_LESS:
390 case GL_GREATER:
391 case GL_EQUAL:
392 case GL_NOTEQUAL:
393 case GL_ALWAYS:
394 case GL_NEVER:
395 break;
396
397 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400399 return false;
400 }
401
402 return true;
403}
404
405template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700406bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
407{
408 if (!context->getExtensions().textureSRGBDecode)
409 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700410 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700411 return false;
412 }
413
414 switch (ConvertToGLenum(params[0]))
415 {
416 case GL_DECODE_EXT:
417 case GL_SKIP_DECODE_EXT:
418 break;
419
420 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700422 return false;
423 }
424
425 return true;
426}
427
Luc Ferron1b1a8642018-01-23 15:12:01 -0500428bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
429{
430 if (!context->getExtensions().textureFilterAnisotropic)
431 {
432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
433 return false;
434 }
435
436 return true;
437}
438
439bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
440{
441 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
442 {
443 return false;
444 }
445
446 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
447
448 if (paramValue < 1 || paramValue > largest)
449 {
450 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
451 return false;
452 }
453
454 return true;
455}
456
Jamie Madill5b772312018-03-08 20:28:32 -0500457bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400458{
459 const Program *program = context->getGLState().getProgram();
460 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
461
Brandon Jonesc405ae72017-12-06 14:15:03 -0800462 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
463 framebuffer->getDrawBufferTypeMask().to_ulong(),
464 program->getActiveOutputVariables().to_ulong(),
465 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400466 {
Brandon Jones76746f92017-11-22 11:44:41 -0800467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
468 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400469 }
470
471 return true;
472}
473
Jamie Madill5b772312018-03-08 20:28:32 -0500474bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400475{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700476 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400477 const Program *program = context->getGLState().getProgram();
478 const VertexArray *vao = context->getGLState().getVertexArray();
479
Brandon Jonesc405ae72017-12-06 14:15:03 -0800480 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
481 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
482 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
483
484 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
485 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
486 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
487
488 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
489 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400490 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800491 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
492 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400493 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400494 return true;
495}
496
Jamie Madill493f9572018-05-24 19:52:15 -0400497bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
498 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800499{
500 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400501 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800502 {
Jamie Madill493f9572018-05-24 19:52:15 -0400503 case PrimitiveMode::Points:
504 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
505 case PrimitiveMode::Lines:
506 case PrimitiveMode::LineStrip:
507 case PrimitiveMode::LineLoop:
508 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
509 case PrimitiveMode::LinesAdjacency:
510 case PrimitiveMode::LineStripAdjacency:
511 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
512 case PrimitiveMode::Triangles:
513 case PrimitiveMode::TriangleFan:
514 case PrimitiveMode::TriangleStrip:
515 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
516 case PrimitiveMode::TrianglesAdjacency:
517 case PrimitiveMode::TriangleStripAdjacency:
518 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800519 default:
520 UNREACHABLE();
521 return false;
522 }
523}
524
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700525// GLES1 texture parameters are a small subset of the others
526bool IsValidGLES1TextureParameter(GLenum pname)
527{
528 switch (pname)
529 {
530 case GL_TEXTURE_MAG_FILTER:
531 case GL_TEXTURE_MIN_FILTER:
532 case GL_TEXTURE_WRAP_S:
533 case GL_TEXTURE_WRAP_T:
534 case GL_TEXTURE_WRAP_R:
535 case GL_GENERATE_MIPMAP:
536 case GL_TEXTURE_CROP_RECT_OES:
537 return true;
538 default:
539 return false;
540 }
541}
542
Geoff Langf41a7152016-09-19 15:11:17 -0400543} // anonymous namespace
544
Brandon Jonesd1049182018-03-28 10:02:20 -0700545void SetRobustLengthParam(GLsizei *length, GLsizei value)
546{
547 if (length)
548 {
549 *length = value;
550 }
551}
552
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500553bool IsETC2EACFormat(const GLenum format)
554{
555 // ES 3.1, Table 8.19
556 switch (format)
557 {
558 case GL_COMPRESSED_R11_EAC:
559 case GL_COMPRESSED_SIGNED_R11_EAC:
560 case GL_COMPRESSED_RG11_EAC:
561 case GL_COMPRESSED_SIGNED_RG11_EAC:
562 case GL_COMPRESSED_RGB8_ETC2:
563 case GL_COMPRESSED_SRGB8_ETC2:
564 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
565 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
566 case GL_COMPRESSED_RGBA8_ETC2_EAC:
567 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
568 return true;
569
570 default:
571 return false;
572 }
573}
574
Jamie Madill5b772312018-03-08 20:28:32 -0500575bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400576{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800577 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400578 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800579 case TextureType::_2D:
580 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800581 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400582
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800583 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400584 return context->getExtensions().textureRectangle;
585
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800586 case TextureType::_3D:
587 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800588 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500589
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800590 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800591 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400592
He Yunchaoced53ae2016-11-29 15:00:51 +0800593 default:
594 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500595 }
Jamie Madill35d15012013-10-07 10:46:37 -0400596}
597
Jamie Madill5b772312018-03-08 20:28:32 -0500598bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500599{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800600 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500601 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800602 case TextureType::_2D:
603 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500604 return true;
605
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800606 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400607 return context->getExtensions().textureRectangle;
608
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500609 default:
610 return false;
611 }
612}
613
Jamie Madill5b772312018-03-08 20:28:32 -0500614bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500615{
616 switch (target)
617 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800618 case TextureType::_3D:
619 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300620 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500621
622 default:
623 return false;
624 }
625}
626
Ian Ewellbda75592016-04-18 17:25:54 -0400627// Most texture GL calls are not compatible with external textures, so we have a separate validation
628// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500629bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400630{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800631 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400632 (context->getExtensions().eglImageExternal ||
633 context->getExtensions().eglStreamConsumerExternal);
634}
635
Shannon Woods4dfed832014-03-17 20:03:39 -0400636// This function differs from ValidTextureTarget in that the target must be
637// usable as the destination of a 2D operation-- so a cube face is valid, but
638// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400639// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500640bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400641{
642 switch (target)
643 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800644 case TextureTarget::_2D:
645 case TextureTarget::CubeMapNegativeX:
646 case TextureTarget::CubeMapNegativeY:
647 case TextureTarget::CubeMapNegativeZ:
648 case TextureTarget::CubeMapPositiveX:
649 case TextureTarget::CubeMapPositiveY:
650 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800651 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800652 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400653 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800654 default:
655 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500656 }
657}
658
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800659bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400660 PrimitiveMode transformFeedbackPrimitiveMode,
661 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800662{
663 ASSERT(context);
664
665 if (!context->getExtensions().geometryShader)
666 {
667 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
668 // that does not match the current transform feedback object's draw mode (if transform
669 // feedback is active), (3.0.2, section 2.14, pg 86)
670 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
671 }
672
673 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400674 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800675 {
Jamie Madill493f9572018-05-24 19:52:15 -0400676 case PrimitiveMode::Points:
677 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
678 case PrimitiveMode::Lines:
679 case PrimitiveMode::LineStrip:
680 case PrimitiveMode::LineLoop:
681 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
682 case PrimitiveMode::Triangles:
683 case PrimitiveMode::TriangleFan:
684 case PrimitiveMode::TriangleStrip:
685 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800686 default:
687 UNREACHABLE();
688 return false;
689 }
690}
691
Jamie Madill5b772312018-03-08 20:28:32 -0500692bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400693 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400694 GLsizei count,
695 GLenum type,
696 const GLvoid *indices,
697 GLsizei primcount)
698{
699 if (primcount < 0)
700 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700701 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400702 return false;
703 }
704
705 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
706 {
707 return false;
708 }
709
Jamie Madill9fdaa492018-02-16 10:52:11 -0500710 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400711}
712
713bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400714 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400715 GLint first,
716 GLsizei count,
717 GLsizei primcount)
718{
719 if (primcount < 0)
720 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700721 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400722 return false;
723 }
724
725 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
726 {
727 return false;
728 }
729
Jamie Madill9fdaa492018-02-16 10:52:11 -0500730 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400731}
732
Jamie Madill5b772312018-03-08 20:28:32 -0500733bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400734{
735 // Verify there is at least one active attribute with a divisor of zero
736 const State &state = context->getGLState();
737
738 Program *program = state.getProgram();
739
740 const auto &attribs = state.getVertexArray()->getVertexAttributes();
741 const auto &bindings = state.getVertexArray()->getVertexBindings();
742 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
743 {
744 const VertexAttribute &attrib = attribs[attributeIndex];
745 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300746 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400747 {
748 return true;
749 }
750 }
751
Brandon Jonesafa75152017-07-21 13:11:29 -0700752 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400753 return false;
754}
755
Jamie Madill5b772312018-03-08 20:28:32 -0500756bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500757{
758 switch (target)
759 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800760 case TextureType::_3D:
761 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800762 return true;
763 default:
764 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400765 }
766}
767
Jamie Madill5b772312018-03-08 20:28:32 -0500768bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800769{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800770 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800771 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800772 case TextureType::_2D:
773 case TextureType::_2DArray:
774 case TextureType::_2DMultisample:
775 case TextureType::CubeMap:
776 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800777 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800778 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400779 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800780 default:
781 return false;
782 }
783}
784
Jamie Madill5b772312018-03-08 20:28:32 -0500785bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500786{
He Yunchaoced53ae2016-11-29 15:00:51 +0800787 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
788 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400789 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500790
791 switch (target)
792 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800793 case GL_FRAMEBUFFER:
794 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400795
He Yunchaoced53ae2016-11-29 15:00:51 +0800796 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800797 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400798 return (context->getExtensions().framebufferBlit ||
799 context->getClientMajorVersion() >= 3);
800
He Yunchaoced53ae2016-11-29 15:00:51 +0800801 default:
802 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500803 }
804}
805
Jamie Madill5b772312018-03-08 20:28:32 -0500806bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400807{
Jamie Madillc29968b2016-01-20 11:17:23 -0500808 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400809 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800810 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400811 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800812 case TextureType::_2D:
813 case TextureType::_2DArray:
814 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500815 maxDimension = caps.max2DTextureSize;
816 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800817 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800818 maxDimension = caps.maxCubeMapTextureSize;
819 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800820 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400821 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800822 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800823 maxDimension = caps.max3DTextureSize;
824 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800825 default:
826 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400827 }
828
Brandon Jones6cad5662017-06-14 13:25:13 -0700829 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400830}
831
Jamie Madill5b772312018-03-08 20:28:32 -0500832bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800833 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700834 GLint level,
835 GLsizei width,
836 GLsizei height,
837 GLsizei depth,
838 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400839{
Brandon Jones6cad5662017-06-14 13:25:13 -0700840 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400841 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700842 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400843 return false;
844 }
Austin Kinross08528e12015-10-07 16:24:40 -0700845 // TexSubImage parameters can be NPOT without textureNPOT extension,
846 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500847 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500848 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500849 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400850 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400851 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700852 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400853 return false;
854 }
855
856 if (!ValidMipLevel(context, target, level))
857 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700858 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400859 return false;
860 }
861
862 return true;
863}
864
Geoff Lang966c9402017-04-18 12:38:27 -0400865bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
866{
867 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
868 (size % blockSize == 0);
869}
870
Jamie Madill5b772312018-03-08 20:28:32 -0500871bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500872 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400873 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500874 GLsizei width,
875 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400876{
Geoff Langca271392017-04-05 12:30:00 -0400877 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400878 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400879 {
880 return false;
881 }
882
Geoff Lang966c9402017-04-18 12:38:27 -0400883 if (width < 0 || height < 0)
884 {
885 return false;
886 }
887
888 if (CompressedTextureFormatRequiresExactSize(internalFormat))
889 {
890 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
891 // block size for level 0 but WebGL disallows this.
892 bool smallerThanBlockSizeAllowed =
893 level > 0 || !context->getExtensions().webglCompatibility;
894
895 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
896 smallerThanBlockSizeAllowed) ||
897 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
898 smallerThanBlockSizeAllowed))
899 {
900 return false;
901 }
902 }
903
904 return true;
905}
906
Jamie Madill5b772312018-03-08 20:28:32 -0500907bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400908 GLenum internalFormat,
909 GLint xoffset,
910 GLint yoffset,
911 GLsizei width,
912 GLsizei height,
913 size_t textureWidth,
914 size_t textureHeight)
915{
916 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
917 if (!formatInfo.compressed)
918 {
919 return false;
920 }
921
Geoff Lang44ff5a72017-02-03 15:15:43 -0500922 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400923 {
924 return false;
925 }
926
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500927 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400928 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500929 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400930 yoffset % formatInfo.compressedBlockHeight != 0)
931 {
932 return false;
933 }
934
935 // Allowed to either have data that is a multiple of block size or is smaller than the block
936 // size but fills the entire mip
937 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
938 static_cast<size_t>(width) == textureWidth &&
939 static_cast<size_t>(height) == textureHeight;
940 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
941 (height % formatInfo.compressedBlockHeight) == 0;
942 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400943 {
944 return false;
945 }
946 }
947
Geoff Langd4f180b2013-09-24 13:57:44 -0400948 return true;
949}
950
Jamie Madill5b772312018-03-08 20:28:32 -0500951bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800952 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400953 GLsizei width,
954 GLsizei height,
955 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400956 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400957 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400958 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400959 GLsizei imageSize)
960{
Corentin Wallez336129f2017-10-17 15:55:40 -0400961 gl::Buffer *pixelUnpackBuffer =
962 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400963 if (pixelUnpackBuffer == nullptr && imageSize < 0)
964 {
965 // Checks are not required
966 return true;
967 }
968
969 // ...the data would be unpacked from the buffer object such that the memory reads required
970 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400971 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
972 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400973 const gl::Extents size(width, height, depth);
974 const auto &unpack = context->getGLState().getUnpackState();
975
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800976 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400977 GLuint endByte = 0;
978 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400979 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400980 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400981 return false;
982 }
983
Geoff Langff5b2d52016-09-07 11:32:23 -0400984 if (pixelUnpackBuffer)
985 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400986 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400987 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
988 checkedEndByte += checkedOffset;
989
990 if (!checkedEndByte.IsValid() ||
991 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
992 {
993 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400994 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400995 return false;
996 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800997 if (context->getExtensions().webglCompatibility &&
998 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
999 {
1000 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1001 PixelUnpackBufferBoundForTransformFeedback);
1002 return false;
1003 }
Geoff Langff5b2d52016-09-07 11:32:23 -04001004 }
1005 else
1006 {
1007 ASSERT(imageSize >= 0);
1008 if (pixels == nullptr && imageSize != 0)
1009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001010 context->handleError(InvalidOperation()
1011 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001012 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001013 }
1014
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001015 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001017 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001018 return false;
1019 }
1020 }
1021
1022 return true;
1023}
1024
Corentin Wallezad3ae902018-03-09 13:40:42 -05001025bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -05001026{
Geoff Lang37dde692014-01-31 16:34:54 -05001027 switch (queryType)
1028 {
Corentin Wallezad3ae902018-03-09 13:40:42 -05001029 case QueryType::AnySamples:
1030 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001031 return context->getClientMajorVersion() >= 3 ||
1032 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001033 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +08001034 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -05001035 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +08001036 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001037 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +08001038 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001039 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +08001040 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 default:
1042 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001043 }
1044}
1045
Jamie Madill5b772312018-03-08 20:28:32 -05001046bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001047 GLenum type,
1048 GLboolean normalized,
1049 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001050 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001051 bool pureInteger)
1052{
1053 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001054 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1055 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1056 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1057 // parameter exceeds 255.
1058 constexpr GLsizei kMaxWebGLStride = 255;
1059 if (stride > kMaxWebGLStride)
1060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001061 context->handleError(InvalidValue()
1062 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001063 return false;
1064 }
1065
1066 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1067 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1068 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1069 // or an INVALID_OPERATION error is generated.
1070 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1071 size_t typeSize = GetVertexFormatTypeSize(internalType);
1072
1073 ASSERT(isPow2(typeSize) && typeSize > 0);
1074 size_t sizeMask = (typeSize - 1);
1075 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1076 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001077 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001078 return false;
1079 }
1080
1081 if ((stride & sizeMask) != 0)
1082 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001084 return false;
1085 }
1086
1087 return true;
1088}
1089
Jamie Madill5b772312018-03-08 20:28:32 -05001090Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001091{
He Yunchaoced53ae2016-11-29 15:00:51 +08001092 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1093 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1094 // or program object and INVALID_OPERATION if the provided name identifies an object
1095 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001096
Dian Xiang769769a2015-09-09 15:20:08 -07001097 Program *validProgram = context->getProgram(id);
1098
1099 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001100 {
Dian Xiang769769a2015-09-09 15:20:08 -07001101 if (context->getShader(id))
1102 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001104 }
1105 else
1106 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001107 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001108 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001109 }
Dian Xiang769769a2015-09-09 15:20:08 -07001110
1111 return validProgram;
1112}
1113
Jamie Madill5b772312018-03-08 20:28:32 -05001114Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001115{
1116 // See ValidProgram for spec details.
1117
1118 Shader *validShader = context->getShader(id);
1119
1120 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001121 {
Dian Xiang769769a2015-09-09 15:20:08 -07001122 if (context->getProgram(id))
1123 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001125 }
1126 else
1127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001128 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001129 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001130 }
Dian Xiang769769a2015-09-09 15:20:08 -07001131
1132 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001133}
1134
Geoff Langb1196682014-07-23 13:47:29 -04001135bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001136{
Geoff Langfa125c92017-10-24 13:01:46 -04001137 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001138 {
Geoff Langfa125c92017-10-24 13:01:46 -04001139 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1140 {
1141 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1142 return false;
1143 }
Jamie Madillb4472272014-07-03 10:38:55 -04001144
Geoff Langfa125c92017-10-24 13:01:46 -04001145 // Color attachment 0 is validated below because it is always valid
1146 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001147 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001148 {
Geoff Langfa125c92017-10-24 13:01:46 -04001149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001150 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001151 }
1152 }
1153 else
1154 {
1155 switch (attachment)
1156 {
Geoff Langfa125c92017-10-24 13:01:46 -04001157 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001158 case GL_DEPTH_ATTACHMENT:
1159 case GL_STENCIL_ATTACHMENT:
1160 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001161
He Yunchaoced53ae2016-11-29 15:00:51 +08001162 case GL_DEPTH_STENCIL_ATTACHMENT:
1163 if (!context->getExtensions().webglCompatibility &&
1164 context->getClientMajorVersion() < 3)
1165 {
Geoff Langfa125c92017-10-24 13:01:46 -04001166 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001167 return false;
1168 }
1169 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001170
He Yunchaoced53ae2016-11-29 15:00:51 +08001171 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001172 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001173 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001174 }
1175 }
1176
1177 return true;
1178}
1179
Jamie Madill5b772312018-03-08 20:28:32 -05001180bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001181 GLenum target,
1182 GLsizei samples,
1183 GLenum internalformat,
1184 GLsizei width,
1185 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001186{
1187 switch (target)
1188 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001189 case GL_RENDERBUFFER:
1190 break;
1191 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001193 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001194 }
1195
1196 if (width < 0 || height < 0 || samples < 0)
1197 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001198 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001199 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001200 }
1201
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001202 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1203 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1204
1205 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001206 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001208 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001209 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001210 }
1211
1212 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1213 // 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 -08001214 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001215 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1216 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001218 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001219 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001220 }
1221
Geoff Langaae65a42014-05-26 12:43:44 -04001222 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001224 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001225 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001226 }
1227
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001228 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001229 if (handle == 0)
1230 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001231 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001232 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001233 }
1234
1235 return true;
1236}
1237
He Yunchaoced53ae2016-11-29 15:00:51 +08001238bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1239 GLenum target,
1240 GLenum attachment,
1241 GLenum renderbuffertarget,
1242 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001243{
Geoff Lange8afa902017-09-27 15:00:43 -04001244 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001246 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001247 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001248 }
1249
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001250 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001251
Jamie Madill84115c92015-04-23 15:00:07 -04001252 ASSERT(framebuffer);
1253 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001254 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001255 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001256 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001257 }
1258
Jamie Madillb4472272014-07-03 10:38:55 -04001259 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001260 {
Jamie Madillb4472272014-07-03 10:38:55 -04001261 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001262 }
1263
Jamie Madillab9d82c2014-01-21 16:38:14 -05001264 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1265 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1266 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1267 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1268 if (renderbuffer != 0)
1269 {
1270 if (!context->getRenderbuffer(renderbuffer))
1271 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001272 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001273 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001274 }
1275 }
1276
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001277 return true;
1278}
1279
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001280bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001281 GLint srcX0,
1282 GLint srcY0,
1283 GLint srcX1,
1284 GLint srcY1,
1285 GLint dstX0,
1286 GLint dstY0,
1287 GLint dstX1,
1288 GLint dstY1,
1289 GLbitfield mask,
1290 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291{
1292 switch (filter)
1293 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001294 case GL_NEAREST:
1295 break;
1296 case GL_LINEAR:
1297 break;
1298 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001299 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001300 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301 }
1302
1303 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1304 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001305 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001306 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001307 }
1308
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001309 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1310 // color buffer, leaving only nearest being unfiltered from above
1311 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001313 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001314 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001315 }
1316
Jamie Madill51f40ec2016-06-15 14:06:00 -04001317 const auto &glState = context->getGLState();
1318 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1319 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001320
1321 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001323 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001324 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 }
1326
Jamie Madill427064d2018-04-13 16:20:34 -04001327 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001328 {
Jamie Madill48faf802014-11-06 15:27:22 -05001329 return false;
1330 }
1331
Jamie Madill427064d2018-04-13 16:20:34 -04001332 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001333 {
Jamie Madill48faf802014-11-06 15:27:22 -05001334 return false;
1335 }
1336
Qin Jiajiaaef92162018-02-27 13:51:44 +08001337 if (readFramebuffer->id() == drawFramebuffer->id())
1338 {
1339 context->handleError(InvalidOperation());
1340 return false;
1341 }
1342
Jamie Madille98b1b52018-03-08 09:47:23 -05001343 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 {
Geoff Langb1196682014-07-23 13:47:29 -04001345 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001346 }
1347
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001348 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1349 // always run it in order to avoid triggering driver bugs.
1350 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1351 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001352 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001353 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1354 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001355 }
1356
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1358
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359 if (mask & GL_COLOR_BUFFER_BIT)
1360 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001361 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001362 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363
He Yunchao66a41a22016-12-15 16:45:05 +08001364 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001366 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367
Geoff Langa15472a2015-08-11 11:48:03 -04001368 for (size_t drawbufferIdx = 0;
1369 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 {
Geoff Langa15472a2015-08-11 11:48:03 -04001371 const FramebufferAttachment *attachment =
1372 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1373 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001374 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001375 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376
Geoff Langb2f3d052013-08-13 12:49:27 -04001377 // The GL ES 3.0.2 spec (pg 193) states that:
1378 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001379 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1380 // as well
1381 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1382 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001383 // Changes with EXT_color_buffer_float:
1384 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001385 GLenum readComponentType = readFormat.info->componentType;
1386 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001387 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001388 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001389 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001390 drawComponentType == GL_SIGNED_NORMALIZED);
1391
1392 if (extensions.colorBufferFloat)
1393 {
1394 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1395 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1396
1397 if (readFixedOrFloat != drawFixedOrFloat)
1398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001399 context->handleError(InvalidOperation()
1400 << "If the read buffer contains fixed-point or "
1401 "floating-point values, the draw buffer must "
1402 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001403 return false;
1404 }
1405 }
1406 else if (readFixedPoint != drawFixedPoint)
1407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001408 context->handleError(InvalidOperation()
1409 << "If the read buffer contains fixed-point values, "
1410 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001411 return false;
1412 }
1413
1414 if (readComponentType == GL_UNSIGNED_INT &&
1415 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001417 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001419 }
1420
Jamie Madill6163c752015-12-07 16:32:59 -05001421 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001424 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 }
1426
Jamie Madilla3944d42016-07-22 22:13:26 -04001427 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001428 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001430 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001431 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 }
Geoff Lange4915782017-04-12 15:19:07 -04001433
1434 if (context->getExtensions().webglCompatibility &&
1435 *readColorBuffer == *attachment)
1436 {
1437 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001438 InvalidOperation()
1439 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001440 return false;
1441 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001442 }
1443 }
1444
Jamie Madilla3944d42016-07-22 22:13:26 -04001445 if ((readFormat.info->componentType == GL_INT ||
1446 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1447 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001449 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001450 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001451 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001452 }
He Yunchao66a41a22016-12-15 16:45:05 +08001453 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1454 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1455 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1456 // situation is an application error that would lead to a crash in ANGLE.
1457 else if (drawFramebuffer->hasEnabledDrawBuffer())
1458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001459 context->handleError(
1460 InvalidOperation()
1461 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001462 return false;
1463 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001464 }
1465
He Yunchaoced53ae2016-11-29 15:00:51 +08001466 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001467 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1468 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001469 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001470 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001471 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001472 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001473 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001474 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001475 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001476
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001477 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001478 {
Kenneth Russell69382852017-07-21 16:38:44 -04001479 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001481 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001482 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001483 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001484
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001485 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001486 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001487 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001488 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001489 }
Geoff Lange4915782017-04-12 15:19:07 -04001490
1491 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1492 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001493 context->handleError(
1494 InvalidOperation()
1495 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001496 return false;
1497 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001498 }
He Yunchao66a41a22016-12-15 16:45:05 +08001499 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1500 else if (drawBuffer)
1501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001502 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1503 "depth/stencil attachment of a "
1504 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001505 return false;
1506 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001507 }
1508 }
1509
Martin Radeva3ed4572017-07-27 18:29:37 +03001510 // ANGLE_multiview, Revision 1:
1511 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001512 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1513 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1514 // views in the current read framebuffer is more than one.
1515 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001516 {
1517 context->handleError(InvalidFramebufferOperation()
1518 << "Attempt to read from a multi-view framebuffer.");
1519 return false;
1520 }
1521 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1522 {
1523 context->handleError(InvalidFramebufferOperation()
1524 << "Attempt to write to a multi-view framebuffer.");
1525 return false;
1526 }
1527
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 return true;
1529}
1530
Jamie Madill4928b7c2017-06-20 12:57:39 -04001531bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001532 GLint x,
1533 GLint y,
1534 GLsizei width,
1535 GLsizei height,
1536 GLenum format,
1537 GLenum type,
1538 GLsizei bufSize,
1539 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001540 GLsizei *columns,
1541 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001542 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001543{
1544 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001545 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001546 return false;
1547 }
1548
Brandon Jonesd1049182018-03-28 10:02:20 -07001549 GLsizei writeLength = 0;
1550 GLsizei writeColumns = 0;
1551 GLsizei writeRows = 0;
1552
1553 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1554 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001555 {
Geoff Langb1196682014-07-23 13:47:29 -04001556 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001557 }
1558
Brandon Jonesd1049182018-03-28 10:02:20 -07001559 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001560 {
Geoff Langb1196682014-07-23 13:47:29 -04001561 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001562 }
1563
Brandon Jonesd1049182018-03-28 10:02:20 -07001564 SetRobustLengthParam(length, writeLength);
1565 SetRobustLengthParam(columns, writeColumns);
1566 SetRobustLengthParam(rows, writeRows);
1567
Jamie Madillc29968b2016-01-20 11:17:23 -05001568 return true;
1569}
1570
1571bool ValidateReadnPixelsEXT(Context *context,
1572 GLint x,
1573 GLint y,
1574 GLsizei width,
1575 GLsizei height,
1576 GLenum format,
1577 GLenum type,
1578 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001579 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001580{
1581 if (bufSize < 0)
1582 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001583 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001584 return false;
1585 }
1586
Geoff Lang62fce5b2016-09-30 10:46:35 -04001587 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001588 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001589}
Jamie Madill26e91952014-03-05 15:01:27 -05001590
Jamie Madill4928b7c2017-06-20 12:57:39 -04001591bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001592 GLint x,
1593 GLint y,
1594 GLsizei width,
1595 GLsizei height,
1596 GLenum format,
1597 GLenum type,
1598 GLsizei bufSize,
1599 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001600 GLsizei *columns,
1601 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001602 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001603{
Brandon Jonesd1049182018-03-28 10:02:20 -07001604 GLsizei writeLength = 0;
1605 GLsizei writeColumns = 0;
1606 GLsizei writeRows = 0;
1607
Geoff Lang62fce5b2016-09-30 10:46:35 -04001608 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001609 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001610 return false;
1611 }
1612
Brandon Jonesd1049182018-03-28 10:02:20 -07001613 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1614 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001615 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001616 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001617 }
1618
Brandon Jonesd1049182018-03-28 10:02:20 -07001619 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001620 {
1621 return false;
1622 }
1623
Brandon Jonesd1049182018-03-28 10:02:20 -07001624 SetRobustLengthParam(length, writeLength);
1625 SetRobustLengthParam(columns, writeColumns);
1626 SetRobustLengthParam(rows, writeRows);
1627
Geoff Lang62fce5b2016-09-30 10:46:35 -04001628 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001629}
1630
Jamie Madillf0e04492017-08-26 15:28:42 -04001631bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001632{
1633 if (!context->getExtensions().occlusionQueryBoolean &&
1634 !context->getExtensions().disjointTimerQuery)
1635 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001637 return false;
1638 }
1639
Olli Etuaho41997e72016-03-10 13:38:39 +02001640 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001641}
1642
Jamie Madillf0e04492017-08-26 15:28:42 -04001643bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001644{
1645 if (!context->getExtensions().occlusionQueryBoolean &&
1646 !context->getExtensions().disjointTimerQuery)
1647 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001649 return false;
1650 }
1651
Olli Etuaho41997e72016-03-10 13:38:39 +02001652 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001653}
1654
Jamie Madillf0e04492017-08-26 15:28:42 -04001655bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1656{
1657 if (!context->getExtensions().occlusionQueryBoolean &&
1658 !context->getExtensions().disjointTimerQuery)
1659 {
1660 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1661 return false;
1662 }
1663
1664 return true;
1665}
1666
Corentin Wallezad3ae902018-03-09 13:40:42 -05001667bool ValidateBeginQueryBase(gl::Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001668{
1669 if (!ValidQueryType(context, target))
1670 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001671 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001672 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001673 }
1674
1675 if (id == 0)
1676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001677 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001678 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001679 }
1680
1681 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1682 // of zero, if the active query object name for <target> is non-zero (for the
1683 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1684 // the active query for either target is non-zero), if <id> is the name of an
1685 // existing query object whose type does not match <target>, or if <id> is the
1686 // active query object name for any query type, the error INVALID_OPERATION is
1687 // generated.
1688
1689 // Ensure no other queries are active
1690 // NOTE: If other queries than occlusion are supported, we will need to check
1691 // separately that:
1692 // a) The query ID passed is not the current active query for any target/type
1693 // b) There are no active queries for the requested target (and in the case
1694 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1695 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001696
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001697 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001699 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001700 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001701 }
1702
1703 Query *queryObject = context->getQuery(id, true, target);
1704
1705 // check that name was obtained with glGenQueries
1706 if (!queryObject)
1707 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001709 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001710 }
1711
1712 // check for type mismatch
1713 if (queryObject->getType() != target)
1714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001715 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001716 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001717 }
1718
1719 return true;
1720}
1721
Corentin Wallezad3ae902018-03-09 13:40:42 -05001722bool ValidateBeginQueryEXT(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001723{
1724 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001725 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001726 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001727 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001728 return false;
1729 }
1730
1731 return ValidateBeginQueryBase(context, target, id);
1732}
1733
Corentin Wallezad3ae902018-03-09 13:40:42 -05001734bool ValidateEndQueryBase(gl::Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001735{
1736 if (!ValidQueryType(context, target))
1737 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001738 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001739 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001740 }
1741
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001742 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001743
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001746 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001747 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001748 }
1749
Jamie Madill45c785d2014-05-13 14:09:34 -04001750 return true;
1751}
1752
Corentin Wallezad3ae902018-03-09 13:40:42 -05001753bool ValidateEndQueryEXT(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001754{
1755 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001756 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001757 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001758 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759 return false;
1760 }
1761
1762 return ValidateEndQueryBase(context, target);
1763}
1764
Corentin Wallezad3ae902018-03-09 13:40:42 -05001765bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001766{
1767 if (!context->getExtensions().disjointTimerQuery)
1768 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001769 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770 return false;
1771 }
1772
Corentin Wallezad3ae902018-03-09 13:40:42 -05001773 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001774 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001775 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001776 return false;
1777 }
1778
1779 Query *queryObject = context->getQuery(id, true, target);
1780 if (queryObject == nullptr)
1781 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001782 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001783 return false;
1784 }
1785
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001786 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001787 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001789 return false;
1790 }
1791
1792 return true;
1793}
1794
Corentin Wallezad3ae902018-03-09 13:40:42 -05001795bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001796{
Geoff Lang2186c382016-10-14 10:54:54 -04001797 if (numParams)
1798 {
1799 *numParams = 0;
1800 }
1801
Corentin Wallezad3ae902018-03-09 13:40:42 -05001802 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001803 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001805 return false;
1806 }
1807
1808 switch (pname)
1809 {
1810 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001811 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001813 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001814 return false;
1815 }
1816 break;
1817 case GL_QUERY_COUNTER_BITS_EXT:
1818 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001819 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001820 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001821 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001822 return false;
1823 }
1824 break;
1825 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001826 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827 return false;
1828 }
1829
Geoff Lang2186c382016-10-14 10:54:54 -04001830 if (numParams)
1831 {
1832 // All queries return only one value
1833 *numParams = 1;
1834 }
1835
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001836 return true;
1837}
1838
Corentin Wallezad3ae902018-03-09 13:40:42 -05001839bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001840{
1841 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001842 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001843 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001845 return false;
1846 }
1847
Geoff Lang2186c382016-10-14 10:54:54 -04001848 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001849}
1850
Geoff Lang2186c382016-10-14 10:54:54 -04001851bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001852 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001853 GLenum pname,
1854 GLsizei bufSize,
1855 GLsizei *length,
1856 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001857{
Geoff Lang2186c382016-10-14 10:54:54 -04001858 if (!ValidateRobustEntryPoint(context, bufSize))
1859 {
1860 return false;
1861 }
1862
Brandon Jonesd1049182018-03-28 10:02:20 -07001863 GLsizei numParams = 0;
1864
1865 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001866 {
1867 return false;
1868 }
1869
Brandon Jonesd1049182018-03-28 10:02:20 -07001870 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001871 {
1872 return false;
1873 }
1874
Brandon Jonesd1049182018-03-28 10:02:20 -07001875 SetRobustLengthParam(length, numParams);
1876
Geoff Lang2186c382016-10-14 10:54:54 -04001877 return true;
1878}
1879
1880bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1881{
1882 if (numParams)
1883 {
1884 *numParams = 0;
1885 }
1886
Corentin Wallezad3ae902018-03-09 13:40:42 -05001887 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001888
1889 if (!queryObject)
1890 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001891 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001892 return false;
1893 }
1894
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001895 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001896 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001897 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001898 return false;
1899 }
1900
1901 switch (pname)
1902 {
1903 case GL_QUERY_RESULT_EXT:
1904 case GL_QUERY_RESULT_AVAILABLE_EXT:
1905 break;
1906
1907 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001908 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001909 return false;
1910 }
1911
Geoff Lang2186c382016-10-14 10:54:54 -04001912 if (numParams)
1913 {
1914 *numParams = 1;
1915 }
1916
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001917 return true;
1918}
1919
1920bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1921{
1922 if (!context->getExtensions().disjointTimerQuery)
1923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001924 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 return false;
1926 }
Geoff Lang2186c382016-10-14 10:54:54 -04001927 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1928}
1929
1930bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1931 GLuint id,
1932 GLenum pname,
1933 GLsizei bufSize,
1934 GLsizei *length,
1935 GLint *params)
1936{
1937 if (!context->getExtensions().disjointTimerQuery)
1938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001939 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001940 return false;
1941 }
1942
1943 if (!ValidateRobustEntryPoint(context, bufSize))
1944 {
1945 return false;
1946 }
1947
Brandon Jonesd1049182018-03-28 10:02:20 -07001948 GLsizei numParams = 0;
1949
1950 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001951 {
1952 return false;
1953 }
1954
Brandon Jonesd1049182018-03-28 10:02:20 -07001955 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001956 {
1957 return false;
1958 }
1959
Brandon Jonesd1049182018-03-28 10:02:20 -07001960 SetRobustLengthParam(length, numParams);
1961
Geoff Lang2186c382016-10-14 10:54:54 -04001962 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001963}
1964
1965bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1966{
1967 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001968 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001970 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001971 return false;
1972 }
Geoff Lang2186c382016-10-14 10:54:54 -04001973 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1974}
1975
1976bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1977 GLuint id,
1978 GLenum pname,
1979 GLsizei bufSize,
1980 GLsizei *length,
1981 GLuint *params)
1982{
1983 if (!context->getExtensions().disjointTimerQuery &&
1984 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001986 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001987 return false;
1988 }
1989
1990 if (!ValidateRobustEntryPoint(context, bufSize))
1991 {
1992 return false;
1993 }
1994
Brandon Jonesd1049182018-03-28 10:02:20 -07001995 GLsizei numParams = 0;
1996
1997 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001998 {
1999 return false;
2000 }
2001
Brandon Jonesd1049182018-03-28 10:02:20 -07002002 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002003 {
2004 return false;
2005 }
2006
Brandon Jonesd1049182018-03-28 10:02:20 -07002007 SetRobustLengthParam(length, numParams);
2008
Geoff Lang2186c382016-10-14 10:54:54 -04002009 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010}
2011
2012bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2013{
2014 if (!context->getExtensions().disjointTimerQuery)
2015 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002016 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002017 return false;
2018 }
Geoff Lang2186c382016-10-14 10:54:54 -04002019 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2020}
2021
2022bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2023 GLuint id,
2024 GLenum pname,
2025 GLsizei bufSize,
2026 GLsizei *length,
2027 GLint64 *params)
2028{
2029 if (!context->getExtensions().disjointTimerQuery)
2030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002032 return false;
2033 }
2034
2035 if (!ValidateRobustEntryPoint(context, bufSize))
2036 {
2037 return false;
2038 }
2039
Brandon Jonesd1049182018-03-28 10:02:20 -07002040 GLsizei numParams = 0;
2041
2042 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002043 {
2044 return false;
2045 }
2046
Brandon Jonesd1049182018-03-28 10:02:20 -07002047 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002048 {
2049 return false;
2050 }
2051
Brandon Jonesd1049182018-03-28 10:02:20 -07002052 SetRobustLengthParam(length, numParams);
2053
Geoff Lang2186c382016-10-14 10:54:54 -04002054 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002055}
2056
2057bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2058{
2059 if (!context->getExtensions().disjointTimerQuery)
2060 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002061 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002062 return false;
2063 }
Geoff Lang2186c382016-10-14 10:54:54 -04002064 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2065}
2066
2067bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2068 GLuint id,
2069 GLenum pname,
2070 GLsizei bufSize,
2071 GLsizei *length,
2072 GLuint64 *params)
2073{
2074 if (!context->getExtensions().disjointTimerQuery)
2075 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002077 return false;
2078 }
2079
2080 if (!ValidateRobustEntryPoint(context, bufSize))
2081 {
2082 return false;
2083 }
2084
Brandon Jonesd1049182018-03-28 10:02:20 -07002085 GLsizei numParams = 0;
2086
2087 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002088 {
2089 return false;
2090 }
2091
Brandon Jonesd1049182018-03-28 10:02:20 -07002092 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002093 {
2094 return false;
2095 }
2096
Brandon Jonesd1049182018-03-28 10:02:20 -07002097 SetRobustLengthParam(length, numParams);
2098
Geoff Lang2186c382016-10-14 10:54:54 -04002099 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002100}
2101
Jamie Madill5b772312018-03-08 20:28:32 -05002102bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002103 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002104 GLint location,
2105 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002106 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002107{
Jiajia Qin5451d532017-11-16 17:16:34 +08002108 // TODO(Jiajia): Add image uniform check in future.
2109 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002110 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002111 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002112 return false;
2113 }
2114
Jiajia Qin5451d532017-11-16 17:16:34 +08002115 if (!program)
2116 {
2117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2118 return false;
2119 }
2120
2121 if (!program->isLinked())
2122 {
2123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2124 return false;
2125 }
2126
2127 if (location == -1)
2128 {
2129 // Silently ignore the uniform command
2130 return false;
2131 }
2132
2133 const auto &uniformLocations = program->getUniformLocations();
2134 size_t castedLocation = static_cast<size_t>(location);
2135 if (castedLocation >= uniformLocations.size())
2136 {
2137 context->handleError(InvalidOperation() << "Invalid uniform location");
2138 return false;
2139 }
2140
2141 const auto &uniformLocation = uniformLocations[castedLocation];
2142 if (uniformLocation.ignored)
2143 {
2144 // Silently ignore the uniform command
2145 return false;
2146 }
2147
2148 if (!uniformLocation.used())
2149 {
2150 context->handleError(InvalidOperation());
2151 return false;
2152 }
2153
2154 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2155
2156 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002157 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002158 {
2159 context->handleError(InvalidOperation());
2160 return false;
2161 }
2162
2163 *uniformOut = &uniform;
2164 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002165}
2166
Jamie Madill5b772312018-03-08 20:28:32 -05002167bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002168 GLenum uniformType,
2169 GLsizei count,
2170 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002171{
Jiajia Qin5451d532017-11-16 17:16:34 +08002172 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2173 // It is compatible with INT or BOOL.
2174 // Do these cheap tests first, for a little extra speed.
2175 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002176 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002177 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002178 }
2179
Jiajia Qin5451d532017-11-16 17:16:34 +08002180 if (IsSamplerType(uniformType))
2181 {
2182 // Check that the values are in range.
2183 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2184 for (GLsizei i = 0; i < count; ++i)
2185 {
2186 if (value[i] < 0 || value[i] >= max)
2187 {
2188 context->handleError(InvalidValue() << "sampler uniform value out of range");
2189 return false;
2190 }
2191 }
2192 return true;
2193 }
2194
2195 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2196 return false;
2197}
2198
Jamie Madill5b772312018-03-08 20:28:32 -05002199bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002200{
2201 // Check that the value type is compatible with uniform type.
2202 // Do the cheaper test first, for a little extra speed.
2203 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2204 {
2205 return true;
2206 }
2207
2208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2209 return false;
2210}
2211
Jamie Madill5b772312018-03-08 20:28:32 -05002212bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002213{
2214 // Check that the value type is compatible with uniform type.
2215 if (valueType == uniformType)
2216 {
2217 return true;
2218 }
2219
2220 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2221 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002222}
2223
Jamie Madill5b772312018-03-08 20:28:32 -05002224bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002225{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002226 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002227 gl::Program *programObject = context->getGLState().getProgram();
2228 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2229 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002230}
2231
Jamie Madill5b772312018-03-08 20:28:32 -05002232bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002233{
2234 const LinkedUniform *uniform = nullptr;
2235 gl::Program *programObject = context->getGLState().getProgram();
2236 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2237 ValidateUniform1ivValue(context, uniform->type, count, value);
2238}
2239
Jamie Madill5b772312018-03-08 20:28:32 -05002240bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002241 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002242 GLint location,
2243 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002244 GLboolean transpose)
2245{
Geoff Lang92019432017-11-20 13:09:34 -05002246 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002248 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002249 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002250 }
2251
Jamie Madill62d31cb2015-09-11 13:25:51 -04002252 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002253 gl::Program *programObject = context->getGLState().getProgram();
2254 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2255 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002256}
2257
Jamie Madill5b772312018-03-08 20:28:32 -05002258bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002259{
2260 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002262 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002263 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002264 }
2265
Jamie Madill0af26e12015-03-05 19:54:33 -05002266 const Caps &caps = context->getCaps();
2267
Jamie Madill893ab082014-05-16 16:56:10 -04002268 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2269 {
2270 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2271
Jamie Madill0af26e12015-03-05 19:54:33 -05002272 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002274 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002275 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002276 }
2277 }
2278
2279 switch (pname)
2280 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002281 case GL_TEXTURE_BINDING_2D:
2282 case GL_TEXTURE_BINDING_CUBE_MAP:
2283 case GL_TEXTURE_BINDING_3D:
2284 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002285 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002286 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002287 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2288 if (!context->getExtensions().textureRectangle)
2289 {
2290 context->handleError(InvalidEnum()
2291 << "ANGLE_texture_rectangle extension not present");
2292 return false;
2293 }
2294 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002295 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2296 if (!context->getExtensions().eglStreamConsumerExternal &&
2297 !context->getExtensions().eglImageExternal)
2298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002299 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2300 "nor GL_OES_EGL_image_external "
2301 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002302 return false;
2303 }
2304 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002305
He Yunchaoced53ae2016-11-29 15:00:51 +08002306 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2307 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002308 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002309 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2310 ASSERT(readFramebuffer);
2311
Jamie Madill427064d2018-04-13 16:20:34 -04002312 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002313 {
Geoff Langb1196682014-07-23 13:47:29 -04002314 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002315 }
2316
Jamie Madille98b1b52018-03-08 09:47:23 -05002317 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002318 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002319 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002320 return false;
2321 }
2322
Jamie Madille98b1b52018-03-08 09:47:23 -05002323 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002324 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002326 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002327 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002328 }
2329 }
2330 break;
2331
He Yunchaoced53ae2016-11-29 15:00:51 +08002332 default:
2333 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002334 }
2335
2336 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002337 if (*numParams == 0)
2338 {
2339 return false;
2340 }
2341
2342 return true;
2343}
2344
Brandon Jonesd1049182018-03-28 10:02:20 -07002345bool ValidateGetBooleanvRobustANGLE(Context *context,
2346 GLenum pname,
2347 GLsizei bufSize,
2348 GLsizei *length,
2349 GLboolean *params)
2350{
2351 GLenum nativeType;
2352 unsigned int numParams = 0;
2353
2354 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2355 {
2356 return false;
2357 }
2358
2359 SetRobustLengthParam(length, numParams);
2360
2361 return true;
2362}
2363
2364bool ValidateGetFloatvRobustANGLE(Context *context,
2365 GLenum pname,
2366 GLsizei bufSize,
2367 GLsizei *length,
2368 GLfloat *params)
2369{
2370 GLenum nativeType;
2371 unsigned int numParams = 0;
2372
2373 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2374 {
2375 return false;
2376 }
2377
2378 SetRobustLengthParam(length, numParams);
2379
2380 return true;
2381}
2382
2383bool ValidateGetIntegervRobustANGLE(Context *context,
2384 GLenum pname,
2385 GLsizei bufSize,
2386 GLsizei *length,
2387 GLint *data)
2388{
2389 GLenum nativeType;
2390 unsigned int numParams = 0;
2391
2392 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2393 {
2394 return false;
2395 }
2396
2397 SetRobustLengthParam(length, numParams);
2398
2399 return true;
2400}
2401
2402bool ValidateGetInteger64vRobustANGLE(Context *context,
2403 GLenum pname,
2404 GLsizei bufSize,
2405 GLsizei *length,
2406 GLint64 *data)
2407{
2408 GLenum nativeType;
2409 unsigned int numParams = 0;
2410
2411 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2412 {
2413 return false;
2414 }
2415
2416 if (nativeType == GL_INT_64_ANGLEX)
2417 {
2418 CastStateValues(context, nativeType, pname, numParams, data);
2419 return false;
2420 }
2421
2422 SetRobustLengthParam(length, numParams);
2423 return true;
2424}
2425
Jamie Madill5b772312018-03-08 20:28:32 -05002426bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002427 GLenum pname,
2428 GLsizei bufSize,
2429 GLenum *nativeType,
2430 unsigned int *numParams)
2431{
2432 if (!ValidateRobustEntryPoint(context, bufSize))
2433 {
2434 return false;
2435 }
2436
2437 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2438 {
2439 return false;
2440 }
2441
2442 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002443 {
2444 return false;
2445 }
2446
2447 return true;
2448}
2449
Jamie Madill5b772312018-03-08 20:28:32 -05002450bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002451 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002452 GLint level,
2453 GLenum internalformat,
2454 bool isSubImage,
2455 GLint xoffset,
2456 GLint yoffset,
2457 GLint zoffset,
2458 GLint x,
2459 GLint y,
2460 GLsizei width,
2461 GLsizei height,
2462 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002463 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002464{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002465 TextureType texType = TextureTargetToType(target);
2466
Brandon Jones6cad5662017-06-14 13:25:13 -07002467 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002468 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002469 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2470 return false;
2471 }
2472
2473 if (width < 0 || height < 0)
2474 {
2475 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002476 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002477 }
2478
He Yunchaoced53ae2016-11-29 15:00:51 +08002479 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2480 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002482 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002483 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002484 }
2485
2486 if (border != 0)
2487 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002488 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002489 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 }
2491
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002492 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002493 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002494 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002495 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002496 }
2497
Jamie Madille98b1b52018-03-08 09:47:23 -05002498 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002499 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002500 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002501 {
Geoff Langb1196682014-07-23 13:47:29 -04002502 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002503 }
2504
Jamie Madille98b1b52018-03-08 09:47:23 -05002505 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002506 {
Geoff Langb1196682014-07-23 13:47:29 -04002507 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002508 }
2509
Martin Radev138064f2016-07-15 12:03:41 +03002510 if (readFramebuffer->getReadBufferState() == GL_NONE)
2511 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002512 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002513 return false;
2514 }
2515
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002516 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2517 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002518 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002519 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002520 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2521 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002522 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002523 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002524 return false;
2525 }
2526
Martin Radev04e2c3b2017-07-27 16:54:35 +03002527 // ANGLE_multiview spec, Revision 1:
2528 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2529 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002530 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2531 // framebuffer is more than one.
2532 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002533 {
2534 context->handleError(InvalidFramebufferOperation()
2535 << "The active read framebuffer object has multiview attachments.");
2536 return false;
2537 }
2538
Geoff Langaae65a42014-05-26 12:43:44 -04002539 const gl::Caps &caps = context->getCaps();
2540
Geoff Langaae65a42014-05-26 12:43:44 -04002541 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002542 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002543 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002544 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002545 maxDimension = caps.max2DTextureSize;
2546 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002547
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002548 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002549 maxDimension = caps.maxCubeMapTextureSize;
2550 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002551
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002552 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002553 maxDimension = caps.maxRectangleTextureSize;
2554 break;
2555
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002556 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002557 maxDimension = caps.max2DTextureSize;
2558 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002559
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002560 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002561 maxDimension = caps.max3DTextureSize;
2562 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002563
He Yunchaoced53ae2016-11-29 15:00:51 +08002564 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002565 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002566 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002567 }
2568
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002569 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002570 if (!texture)
2571 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002572 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002573 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002574 }
2575
Geoff Lang69cce582015-09-17 13:20:36 -04002576 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002578 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002579 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002580 }
2581
Geoff Langca271392017-04-05 12:30:00 -04002582 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002583 isSubImage ? *texture->getFormat(target, level).info
2584 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002585
Geoff Lang966c9402017-04-18 12:38:27 -04002586 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002588 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002589 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002590 }
2591
2592 if (isSubImage)
2593 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002594 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2595 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2596 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002598 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002599 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002600 }
2601 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002602 else
2603 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002604 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002605 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002606 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002607 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002608 }
2609
Geoff Langeb66a6e2016-10-31 13:06:12 -04002610 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002611 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002612 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002613 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002614 }
2615
2616 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002617 if (static_cast<int>(width) > maxLevelDimension ||
2618 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002619 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002620 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002621 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002622 }
2623 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002624
Jamie Madill0c8abca2016-07-22 20:21:26 -04002625 if (textureFormatOut)
2626 {
2627 *textureFormatOut = texture->getFormat(target, level);
2628 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002629
2630 // Detect texture copying feedback loops for WebGL.
2631 if (context->getExtensions().webglCompatibility)
2632 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002633 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002634 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002635 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002636 return false;
2637 }
2638 }
2639
Jamie Madill560a8d82014-05-21 13:06:20 -04002640 return true;
2641}
2642
Jamie Madill493f9572018-05-24 19:52:15 -04002643bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002644{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002645 const Extensions &extensions = context->getExtensions();
2646
Jamie Madill1aeb1312014-06-20 13:21:25 -04002647 switch (mode)
2648 {
Jamie Madill493f9572018-05-24 19:52:15 -04002649 case PrimitiveMode::Points:
2650 case PrimitiveMode::Lines:
2651 case PrimitiveMode::LineLoop:
2652 case PrimitiveMode::LineStrip:
2653 case PrimitiveMode::Triangles:
2654 case PrimitiveMode::TriangleStrip:
2655 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002656 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002657
Jamie Madill493f9572018-05-24 19:52:15 -04002658 case PrimitiveMode::LinesAdjacency:
2659 case PrimitiveMode::LineStripAdjacency:
2660 case PrimitiveMode::TrianglesAdjacency:
2661 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002662 if (!extensions.geometryShader)
2663 {
2664 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2665 return false;
2666 }
2667 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002668 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002669 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002670 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002671 }
2672
Jamie Madill250d33f2014-06-06 17:09:03 -04002673 if (count < 0)
2674 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002675 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002676 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002677 }
2678
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002679 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002680
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002681 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2682 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2683 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2684 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002685 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002686 // Check for mapped buffers
2687 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002688 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002689 {
2690 context->handleError(InvalidOperation());
2691 return false;
2692 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002693 }
2694
Jamie Madillcbcde722017-01-06 14:50:00 -05002695 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2696 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002697 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002698 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002699 {
Ken Russellb9f92502018-01-27 19:00:26 -08002700 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002701 const FramebufferAttachment *dsAttachment =
2702 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002703 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2704 ASSERT(stencilBits <= 8);
2705
Jinyoung Hur85769f02015-10-20 17:08:44 -04002706 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002707 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002708 {
Ken Russellb9f92502018-01-27 19:00:26 -08002709 GLuint maxStencilValue = (1 << stencilBits) - 1;
2710
2711 bool differentRefs =
2712 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2713 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2714 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2715 (depthStencilState.stencilBackWritemask & maxStencilValue);
2716 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2717 (depthStencilState.stencilBackMask & maxStencilValue);
2718
2719 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002720 {
Ken Russellb9f92502018-01-27 19:00:26 -08002721 if (!extensions.webglCompatibility)
2722 {
Jamie Madilla2f043d2018-07-10 17:21:20 -04002723 WARN() << "This ANGLE implementation does not support separate front/back "
2724 "stencil writemasks, reference values, or stencil mask values.";
Ken Russellb9f92502018-01-27 19:00:26 -08002725 }
2726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2727 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002728 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002729 }
Jamie Madillac528012014-06-20 13:21:23 -04002730 }
2731
Jamie Madill427064d2018-04-13 16:20:34 -04002732 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002733 {
Geoff Langb1196682014-07-23 13:47:29 -04002734 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002735 }
2736
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002737 // If we are running GLES1, there is no current program.
2738 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002739 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002740
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002741 gl::Program *program = state.getProgram();
2742 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002743 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002744 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002745 return false;
2746 }
Martin Radev7e69f762017-07-27 14:54:13 +03002747
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002748 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2749 // vertex shader stage or fragment shader stage is a undefined behaviour.
2750 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2751 // produce undefined result.
2752 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2753 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002754 {
2755 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002756 << "It is a undefined behaviour to render without "
2757 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002758 return false;
2759 }
Martin Radevffe754b2017-07-31 10:38:07 +03002760
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002761 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002762 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002763 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002764 return false;
2765 }
2766
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002767 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002768 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002769 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2770 const int framebufferNumViews = framebuffer->getNumViews();
2771 if (framebufferNumViews != programNumViews)
2772 {
2773 context->handleError(InvalidOperation()
2774 << "The number of views in the active program "
2775 "and draw framebuffer does not match.");
2776 return false;
2777 }
2778
2779 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2780 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2781 framebufferNumViews > 1)
2782 {
2783 context->handleError(InvalidOperation()
2784 << "There is an active transform feedback object "
2785 "when the number of views in the active draw "
2786 "framebuffer is greater than 1.");
2787 return false;
2788 }
2789
2790 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2791 state.isQueryActive(QueryType::TimeElapsed))
2792 {
2793 context->handleError(InvalidOperation()
2794 << "There is an active query for target "
2795 "GL_TIME_ELAPSED_EXT when the number of "
2796 "views in the active draw framebuffer is "
2797 "greater than 1.");
2798 return false;
2799 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002800 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002801
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002802 // Do geometry shader specific validations
2803 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002804 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002805 if (!IsCompatibleDrawModeWithGeometryShader(
2806 mode, program->getGeometryShaderInputPrimitiveType()))
2807 {
2808 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2809 IncompatibleDrawModeAgainstGeometryShader);
2810 return false;
2811 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002812 }
Geoff Lange0cff192017-05-30 13:04:56 -04002813
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002814 // Uniform buffer validation
2815 for (unsigned int uniformBlockIndex = 0;
2816 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002817 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002818 const gl::InterfaceBlock &uniformBlock =
2819 program->getUniformBlockByIndex(uniformBlockIndex);
2820 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2821 const OffsetBindingPointer<Buffer> &uniformBuffer =
2822 state.getIndexedUniformBuffer(blockBinding);
2823
2824 if (uniformBuffer.get() == nullptr)
2825 {
2826 // undefined behaviour
2827 context->handleError(
2828 InvalidOperation()
2829 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2830 return false;
2831 }
2832
2833 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2834 if (uniformBufferSize < uniformBlock.dataSize)
2835 {
2836 // undefined behaviour
2837 context->handleError(
2838 InvalidOperation()
2839 << "It is undefined behaviour to use a uniform buffer that is too small.");
2840 return false;
2841 }
2842
2843 if (extensions.webglCompatibility &&
2844 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2845 {
2846 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2847 UniformBufferBoundForTransformFeedback);
2848 return false;
2849 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002850 }
2851
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002852 // Do some additonal WebGL-specific validation
2853 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002854 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002855 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2856 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2857 transformFeedbackObject->buffersBoundForOtherUse())
2858 {
2859 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2860 TransformFeedbackBufferDoubleBound);
2861 return false;
2862 }
2863 // Detect rendering feedback loops for WebGL.
2864 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2865 {
2866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2867 return false;
2868 }
2869
2870 // Detect that the vertex shader input types match the attribute types
2871 if (!ValidateVertexShaderAttributeTypeMatch(context))
2872 {
2873 return false;
2874 }
2875
2876 // Detect that the color buffer types match the fragment shader output types
2877 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2878 {
2879 return false;
2880 }
Jamie Madillac43aaa2018-07-31 11:22:13 -04002881
2882 if (count > 0)
2883 {
2884 const VertexArray *vao = context->getGLState().getVertexArray();
2885 if (vao->hasTransformFeedbackBindingConflict(context))
2886 {
2887 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2888 VertexBufferBoundForTransformFeedback);
2889 return false;
2890 }
2891 }
Geoff Lange0cff192017-05-30 13:04:56 -04002892 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002893 }
2894
Jamie Madill9fdaa492018-02-16 10:52:11 -05002895 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002896}
2897
Jamie Madill5b772312018-03-08 20:28:32 -05002898bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002899 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002900 GLint first,
2901 GLsizei count,
2902 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002903{
Jamie Madillfd716582014-06-06 17:09:04 -04002904 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002905 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002906 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002907 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002908 }
2909
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002910 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002911 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002912 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002913 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002914 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002915 if (!ValidateTransformFeedbackPrimitiveMode(context,
2916 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002917 {
James Darpinian30b604d2018-03-12 17:26:57 -07002918 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2919 return false;
2920 }
2921
2922 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2923 {
2924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2925 return false;
2926 }
Jamie Madillfd716582014-06-06 17:09:04 -04002927 }
2928
Jiajia Qind9671222016-11-29 16:30:31 +08002929 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002930 {
2931 return false;
2932 }
2933
Corentin Wallez71168a02016-12-19 15:11:18 -08002934 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002935 // - first < 0 has been checked as an error condition.
2936 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002937 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002938 ASSERT(first >= 0);
2939 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002940 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002941 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2942 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2943 {
2944 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2945 return false;
2946 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002947
Jamie Madill9fdaa492018-02-16 10:52:11 -05002948 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2949 {
2950 return false;
2951 }
Jamie Madillfd716582014-06-06 17:09:04 -04002952 }
2953
2954 return true;
2955}
2956
He Yunchaoced53ae2016-11-29 15:00:51 +08002957bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002958 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002959 GLint first,
2960 GLsizei count,
2961 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002962{
Geoff Lang63c5a592017-09-27 14:08:16 -04002963 if (!context->getExtensions().instancedArrays)
2964 {
2965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2966 return false;
2967 }
2968
Corentin Wallez170efbf2017-05-02 13:45:01 -04002969 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002970 {
2971 return false;
2972 }
2973
Corentin Wallez0dc97812017-06-22 14:38:44 -04002974 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002975}
2976
Jamie Madill493f9572018-05-24 19:52:15 -04002977bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002978{
Jamie Madill250d33f2014-06-06 17:09:03 -04002979 switch (type)
2980 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002981 case GL_UNSIGNED_BYTE:
2982 case GL_UNSIGNED_SHORT:
2983 break;
2984 case GL_UNSIGNED_INT:
2985 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002987 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002988 return false;
2989 }
2990 break;
2991 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002992 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002993 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002994 }
2995
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002996 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002997
2998 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002999 if (curTransformFeedback && curTransformFeedback->isActive() &&
3000 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003001 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003002 // EXT_geometry_shader allows transform feedback to work with all draw commands.
3003 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
3004 if (context->getExtensions().geometryShader)
3005 {
3006 if (!ValidateTransformFeedbackPrimitiveMode(
3007 context, curTransformFeedback->getPrimitiveMode(), mode))
3008 {
3009 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
3010 return false;
3011 }
3012 }
3013 else
3014 {
3015 // It is an invalid operation to call DrawElements, DrawRangeElements or
3016 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
3017 // 86)
3018 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3019 UnsupportedDrawModeForTransformFeedback);
3020 return false;
3021 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003022 }
3023
Jiajia Qind9671222016-11-29 16:30:31 +08003024 return true;
3025}
3026
Jamie Madill5b772312018-03-08 20:28:32 -05003027bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003028 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003029 GLsizei count,
3030 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003031 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003032 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003033{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003034 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003035 return false;
3036
3037 const State &state = context->getGLState();
3038
Corentin Wallez170efbf2017-05-02 13:45:01 -04003039 if (!ValidateDrawBase(context, mode, count))
3040 {
3041 return false;
3042 }
3043
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003044 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
3045 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3046 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3047 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04003048 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003049 // Check for mapped buffers
3050 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04003051 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003052 {
3053 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3054 return false;
3055 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003056 }
3057
He Yunchaoced53ae2016-11-29 15:00:51 +08003058 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003059 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003060
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003061 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3062
3063 if (context->getExtensions().webglCompatibility)
3064 {
3065 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3066 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3067 {
3068 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3069 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3070 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003072 return false;
3073 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003074
3075 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3076 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3077 // error is generated.
3078 if (reinterpret_cast<intptr_t>(indices) < 0)
3079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003080 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003081 return false;
3082 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003083 }
3084
3085 if (context->getExtensions().webglCompatibility ||
3086 !context->getGLState().areClientArraysEnabled())
3087 {
Brandon Jones2a018152018-06-08 15:59:26 -07003088 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003089 {
3090 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003091 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3092 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003093 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003094 return false;
3095 }
3096 }
3097
Jamie Madill9fdaa492018-02-16 10:52:11 -05003098 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003099 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003100 // This is an application error that would normally result in a crash, but we catch it and
3101 // return an error
3102 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3103 return false;
3104 }
3105
3106 if (count > 0 && elementArrayBuffer)
3107 {
3108 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3109 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3110 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3111 constexpr uint64_t kMaxTypeSize = 8;
3112 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3113 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3114 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3115
3116 uint64_t typeSize = typeBytes;
3117 uint64_t elementCount = static_cast<uint64_t>(count);
3118 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3119
3120 // Doing the multiplication here is overflow-safe
3121 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3122
3123 // The offset can be any value, check for overflows
3124 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3125 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003126 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3128 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003129 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003130
3131 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3132 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003133 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3135 return false;
3136 }
3137
3138 ASSERT(isPow2(typeSize) && typeSize > 0);
3139 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3140 {
3141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003142 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003143 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003144
3145 if (context->getExtensions().webglCompatibility &&
3146 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3147 {
3148 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3149 ElementArrayBufferBoundForTransformFeedback);
3150 return false;
3151 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003152 }
3153
Jamie Madillac43aaa2018-07-31 11:22:13 -04003154 if (context->getExtensions().robustBufferAccessBehavior || count == 0)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003155 {
Jamie Madillac43aaa2018-07-31 11:22:13 -04003156 // Special checks are needed for client attribs. But we don't need to validate overflows.
3157 if (!ValidateDrawClientAttribs(context))
Jamie Madill9fdaa492018-02-16 10:52:11 -05003158 {
3159 return false;
3160 }
3161 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003162 else
3163 {
3164 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003165 const DrawCallParams &params = context->getParams<DrawCallParams>();
3166 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3167 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003168
3169 // If we use an index greater than our maximum supported index range, return an error.
3170 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3171 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003172 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003173 {
3174 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3175 return false;
3176 }
3177
Jamie Madill6f5444d2018-03-14 10:08:11 -04003178 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3179 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003180 {
3181 return false;
3182 }
3183
3184 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003185 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003186 }
3187
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003188 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003189}
3190
Jamie Madill5b772312018-03-08 20:28:32 -05003191bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003192 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003193 GLsizei count,
3194 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003195 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003196 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003197{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003198 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003199}
3200
Geoff Lang3edfe032015-09-04 16:38:24 -04003201bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003202 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003203 GLsizei count,
3204 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003205 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003206 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003207{
Geoff Lang63c5a592017-09-27 14:08:16 -04003208 if (!context->getExtensions().instancedArrays)
3209 {
3210 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3211 return false;
3212 }
3213
Corentin Wallez170efbf2017-05-02 13:45:01 -04003214 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003215 {
3216 return false;
3217 }
3218
Corentin Wallez0dc97812017-06-22 14:38:44 -04003219 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003220}
3221
He Yunchaoced53ae2016-11-29 15:00:51 +08003222bool ValidateFramebufferTextureBase(Context *context,
3223 GLenum target,
3224 GLenum attachment,
3225 GLuint texture,
3226 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003227{
Geoff Lange8afa902017-09-27 15:00:43 -04003228 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003229 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003230 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003231 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003232 }
3233
3234 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003235 {
3236 return false;
3237 }
3238
Jamie Madill55ec3b12014-07-03 10:38:57 -04003239 if (texture != 0)
3240 {
3241 gl::Texture *tex = context->getTexture(texture);
3242
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003243 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003245 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003246 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003247 }
3248
3249 if (level < 0)
3250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003251 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003252 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003253 }
3254 }
3255
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003256 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003257 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003258
Jamie Madill84115c92015-04-23 15:00:07 -04003259 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003261 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003262 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003263 }
3264
3265 return true;
3266}
3267
Geoff Langb1196682014-07-23 13:47:29 -04003268bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003269{
3270 if (program == 0)
3271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003272 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003273 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003274 }
3275
Dian Xiang769769a2015-09-09 15:20:08 -07003276 gl::Program *programObject = GetValidProgram(context, program);
3277 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003278 {
3279 return false;
3280 }
3281
Jamie Madill0063c512014-08-25 15:47:53 -04003282 if (!programObject || !programObject->isLinked())
3283 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003285 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003286 }
3287
Geoff Lang7dd2e102014-11-10 15:19:26 -05003288 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003290 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003291 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003292 }
3293
Jamie Madill0063c512014-08-25 15:47:53 -04003294 return true;
3295}
3296
Geoff Langf41d0ee2016-10-07 13:04:23 -04003297static bool ValidateSizedGetUniform(Context *context,
3298 GLuint program,
3299 GLint location,
3300 GLsizei bufSize,
3301 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003302{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003303 if (length)
3304 {
3305 *length = 0;
3306 }
3307
Jamie Madill78f41802014-08-25 15:47:55 -04003308 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003309 {
Jamie Madill78f41802014-08-25 15:47:55 -04003310 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003311 }
3312
Geoff Langf41d0ee2016-10-07 13:04:23 -04003313 if (bufSize < 0)
3314 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003315 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003316 return false;
3317 }
3318
Jamie Madilla502c742014-08-28 17:19:13 -04003319 gl::Program *programObject = context->getProgram(program);
3320 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003321
Jamie Madill78f41802014-08-25 15:47:55 -04003322 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003323 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003324 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003325 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003326 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003327 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003328 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003329 }
3330
Geoff Langf41d0ee2016-10-07 13:04:23 -04003331 if (length)
3332 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003333 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003334 }
3335
Jamie Madill0063c512014-08-25 15:47:53 -04003336 return true;
3337}
3338
He Yunchaoced53ae2016-11-29 15:00:51 +08003339bool ValidateGetnUniformfvEXT(Context *context,
3340 GLuint program,
3341 GLint location,
3342 GLsizei bufSize,
3343 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003344{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003345 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003346}
3347
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003348bool ValidateGetnUniformfvRobustANGLE(Context *context,
3349 GLuint program,
3350 GLint location,
3351 GLsizei bufSize,
3352 GLsizei *length,
3353 GLfloat *params)
3354{
3355 UNIMPLEMENTED();
3356 return false;
3357}
3358
He Yunchaoced53ae2016-11-29 15:00:51 +08003359bool ValidateGetnUniformivEXT(Context *context,
3360 GLuint program,
3361 GLint location,
3362 GLsizei bufSize,
3363 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003364{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003365 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3366}
3367
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003368bool ValidateGetnUniformivRobustANGLE(Context *context,
3369 GLuint program,
3370 GLint location,
3371 GLsizei bufSize,
3372 GLsizei *length,
3373 GLint *params)
3374{
3375 UNIMPLEMENTED();
3376 return false;
3377}
3378
3379bool ValidateGetnUniformuivRobustANGLE(Context *context,
3380 GLuint program,
3381 GLint location,
3382 GLsizei bufSize,
3383 GLsizei *length,
3384 GLuint *params)
3385{
3386 UNIMPLEMENTED();
3387 return false;
3388}
3389
Geoff Langf41d0ee2016-10-07 13:04:23 -04003390bool ValidateGetUniformfvRobustANGLE(Context *context,
3391 GLuint program,
3392 GLint location,
3393 GLsizei bufSize,
3394 GLsizei *length,
3395 GLfloat *params)
3396{
3397 if (!ValidateRobustEntryPoint(context, bufSize))
3398 {
3399 return false;
3400 }
3401
Brandon Jonesd1049182018-03-28 10:02:20 -07003402 GLsizei writeLength = 0;
3403
Geoff Langf41d0ee2016-10-07 13:04:23 -04003404 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003405 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3406 {
3407 return false;
3408 }
3409
3410 SetRobustLengthParam(length, writeLength);
3411
3412 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003413}
3414
3415bool ValidateGetUniformivRobustANGLE(Context *context,
3416 GLuint program,
3417 GLint location,
3418 GLsizei bufSize,
3419 GLsizei *length,
3420 GLint *params)
3421{
3422 if (!ValidateRobustEntryPoint(context, bufSize))
3423 {
3424 return false;
3425 }
3426
Brandon Jonesd1049182018-03-28 10:02:20 -07003427 GLsizei writeLength = 0;
3428
Geoff Langf41d0ee2016-10-07 13:04:23 -04003429 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003430 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3431 {
3432 return false;
3433 }
3434
3435 SetRobustLengthParam(length, writeLength);
3436
3437 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003438}
3439
3440bool ValidateGetUniformuivRobustANGLE(Context *context,
3441 GLuint program,
3442 GLint location,
3443 GLsizei bufSize,
3444 GLsizei *length,
3445 GLuint *params)
3446{
3447 if (!ValidateRobustEntryPoint(context, bufSize))
3448 {
3449 return false;
3450 }
3451
3452 if (context->getClientMajorVersion() < 3)
3453 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003454 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003455 return false;
3456 }
3457
Brandon Jonesd1049182018-03-28 10:02:20 -07003458 GLsizei writeLength = 0;
3459
Geoff Langf41d0ee2016-10-07 13:04:23 -04003460 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003461 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3462 {
3463 return false;
3464 }
3465
3466 SetRobustLengthParam(length, writeLength);
3467
3468 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003469}
3470
He Yunchaoced53ae2016-11-29 15:00:51 +08003471bool ValidateDiscardFramebufferBase(Context *context,
3472 GLenum target,
3473 GLsizei numAttachments,
3474 const GLenum *attachments,
3475 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003476{
3477 if (numAttachments < 0)
3478 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003479 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003480 return false;
3481 }
3482
3483 for (GLsizei i = 0; i < numAttachments; ++i)
3484 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003485 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003486 {
3487 if (defaultFramebuffer)
3488 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003489 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003490 return false;
3491 }
3492
3493 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003495 context->handleError(InvalidOperation() << "Requested color attachment is "
3496 "greater than the maximum supported "
3497 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003498 return false;
3499 }
3500 }
3501 else
3502 {
3503 switch (attachments[i])
3504 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003505 case GL_DEPTH_ATTACHMENT:
3506 case GL_STENCIL_ATTACHMENT:
3507 case GL_DEPTH_STENCIL_ATTACHMENT:
3508 if (defaultFramebuffer)
3509 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003510 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3511 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003512 return false;
3513 }
3514 break;
3515 case GL_COLOR:
3516 case GL_DEPTH:
3517 case GL_STENCIL:
3518 if (!defaultFramebuffer)
3519 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003520 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3521 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003522 return false;
3523 }
3524 break;
3525 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003526 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003527 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003528 }
3529 }
3530 }
3531
3532 return true;
3533}
3534
Austin Kinross6ee1e782015-05-29 17:05:37 -07003535bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3536{
Jamie Madill007530e2017-12-28 14:27:04 -05003537 if (!context->getExtensions().debugMarker)
3538 {
3539 // The debug marker calls should not set error state
3540 // However, it seems reasonable to set an error state if the extension is not enabled
3541 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3542 return false;
3543 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003544
Jamie Madill007530e2017-12-28 14:27:04 -05003545 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003546 if (length < 0)
3547 {
3548 return false;
3549 }
3550
3551 if (marker == nullptr)
3552 {
3553 return false;
3554 }
3555
3556 return true;
3557}
3558
3559bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3560{
Jamie Madill007530e2017-12-28 14:27:04 -05003561 if (!context->getExtensions().debugMarker)
3562 {
3563 // The debug marker calls should not set error state
3564 // However, it seems reasonable to set an error state if the extension is not enabled
3565 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3566 return false;
3567 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003568
Jamie Madill007530e2017-12-28 14:27:04 -05003569 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003570 if (length < 0)
3571 {
3572 return false;
3573 }
3574
3575 if (length > 0 && marker == nullptr)
3576 {
3577 return false;
3578 }
3579
3580 return true;
3581}
3582
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003583bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003584{
Geoff Langa8406172015-07-21 16:53:39 -04003585 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003587 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003588 return false;
3589 }
3590
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003591 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003592 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003593 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003594 if (!context->getExtensions().eglImage)
3595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003596 context->handleError(InvalidEnum()
3597 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003598 }
3599 break;
3600
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003601 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003602 if (!context->getExtensions().eglImageExternal)
3603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003604 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3605 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003606 }
Geoff Langa8406172015-07-21 16:53:39 -04003607 break;
3608
3609 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003610 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003611 return false;
3612 }
3613
Rafael Cintron05a449a2018-06-20 18:08:04 -07003614 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003615
Jamie Madill61e16b42017-06-19 11:13:23 -04003616 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003617 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003619 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003620 return false;
3621 }
3622
Jamie Madill007530e2017-12-28 14:27:04 -05003623 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003625 context->handleError(InvalidOperation()
3626 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003627 return false;
3628 }
3629
Geoff Langca271392017-04-05 12:30:00 -04003630 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003631 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003632 if (!textureCaps.texturable)
3633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003634 context->handleError(InvalidOperation()
3635 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003636 return false;
3637 }
3638
Geoff Langdcab33b2015-07-21 13:03:16 -04003639 return true;
3640}
3641
3642bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003643 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003644 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003645{
Geoff Langa8406172015-07-21 16:53:39 -04003646 if (!context->getExtensions().eglImage)
3647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003648 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003649 return false;
3650 }
3651
3652 switch (target)
3653 {
3654 case GL_RENDERBUFFER:
3655 break;
3656
3657 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003659 return false;
3660 }
3661
Rafael Cintron05a449a2018-06-20 18:08:04 -07003662 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003663
Jamie Madill61e16b42017-06-19 11:13:23 -04003664 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003665 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003667 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003668 return false;
3669 }
3670
Geoff Langca271392017-04-05 12:30:00 -04003671 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003672 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003673 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003675 context->handleError(InvalidOperation()
3676 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003677 return false;
3678 }
3679
Geoff Langdcab33b2015-07-21 13:03:16 -04003680 return true;
3681}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003682
3683bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3684{
Geoff Lang36167ab2015-12-07 10:27:14 -05003685 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003686 {
3687 // The default VAO should always exist
3688 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003689 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003690 return false;
3691 }
3692
3693 return true;
3694}
3695
Geoff Langc5629752015-12-07 16:29:04 -05003696bool ValidateProgramBinaryBase(Context *context,
3697 GLuint program,
3698 GLenum binaryFormat,
3699 const void *binary,
3700 GLint length)
3701{
3702 Program *programObject = GetValidProgram(context, program);
3703 if (programObject == nullptr)
3704 {
3705 return false;
3706 }
3707
3708 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3709 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3710 programBinaryFormats.end())
3711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003712 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003713 return false;
3714 }
3715
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003716 if (context->hasActiveTransformFeedback(program))
3717 {
3718 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003719 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3720 "is associated with an active transform "
3721 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003722 return false;
3723 }
3724
Geoff Langc5629752015-12-07 16:29:04 -05003725 return true;
3726}
3727
3728bool ValidateGetProgramBinaryBase(Context *context,
3729 GLuint program,
3730 GLsizei bufSize,
3731 GLsizei *length,
3732 GLenum *binaryFormat,
3733 void *binary)
3734{
3735 Program *programObject = GetValidProgram(context, program);
3736 if (programObject == nullptr)
3737 {
3738 return false;
3739 }
3740
3741 if (!programObject->isLinked())
3742 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003743 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003744 return false;
3745 }
3746
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003747 if (context->getCaps().programBinaryFormats.empty())
3748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003749 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003750 return false;
3751 }
3752
Geoff Langc5629752015-12-07 16:29:04 -05003753 return true;
3754}
Jamie Madillc29968b2016-01-20 11:17:23 -05003755
Jamie Madill5b772312018-03-08 20:28:32 -05003756bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003757{
3758 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003759 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003760 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003761 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3762 return false;
3763 }
3764 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3765 {
3766 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003767 return false;
3768 }
3769
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003770 ASSERT(context->getGLState().getDrawFramebuffer());
3771 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003772 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3773
3774 // This should come first before the check for the default frame buffer
3775 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3776 // rather than INVALID_OPERATION
3777 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3778 {
3779 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3780
3781 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003782 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3783 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003784 {
3785 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003786 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3787 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3788 // 3.1 is still a bit ambiguous about the error, but future specs are
3789 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003790 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003791 return false;
3792 }
3793 else if (bufs[colorAttachment] >= maxColorAttachment)
3794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003795 context->handleError(InvalidOperation()
3796 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003797 return false;
3798 }
3799 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3800 frameBufferId != 0)
3801 {
3802 // INVALID_OPERATION-GL is bound to buffer and ith argument
3803 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003804 context->handleError(InvalidOperation()
3805 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003806 return false;
3807 }
3808 }
3809
3810 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3811 // and n is not 1 or bufs is bound to value other than BACK and NONE
3812 if (frameBufferId == 0)
3813 {
3814 if (n != 1)
3815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003816 context->handleError(InvalidOperation()
3817 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003818 return false;
3819 }
3820
3821 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003823 context->handleError(
3824 InvalidOperation()
3825 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003826 return false;
3827 }
3828 }
3829
3830 return true;
3831}
3832
Geoff Lang496c02d2016-10-20 11:38:11 -07003833bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003834 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003835 GLenum pname,
3836 GLsizei *length,
3837 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003838{
Geoff Lang496c02d2016-10-20 11:38:11 -07003839 if (length)
3840 {
3841 *length = 0;
3842 }
3843
3844 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3845 {
3846 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003847 InvalidOperation()
3848 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003849 return false;
3850 }
3851
Corentin Walleze4477002017-12-01 14:39:58 -05003852 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003853 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003854 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003855 return false;
3856 }
3857
Geoff Lang496c02d2016-10-20 11:38:11 -07003858 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003859 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003860 case GL_BUFFER_MAP_POINTER:
3861 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003862
Geoff Lang496c02d2016-10-20 11:38:11 -07003863 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003864 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003865 return false;
3866 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003867
3868 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3869 // target bound to zero generate an INVALID_OPERATION error."
3870 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003871 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003872 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003873 context->handleError(InvalidOperation()
3874 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003875 return false;
3876 }
3877
Geoff Lang496c02d2016-10-20 11:38:11 -07003878 if (length)
3879 {
3880 *length = 1;
3881 }
3882
Olli Etuaho4f667482016-03-30 15:56:35 +03003883 return true;
3884}
3885
Corentin Wallez336129f2017-10-17 15:55:40 -04003886bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003887{
Corentin Walleze4477002017-12-01 14:39:58 -05003888 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003889 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003890 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003891 return false;
3892 }
3893
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003894 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003895
3896 if (buffer == nullptr || !buffer->isMapped())
3897 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003898 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003899 return false;
3900 }
3901
3902 return true;
3903}
3904
3905bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003906 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003907 GLintptr offset,
3908 GLsizeiptr length,
3909 GLbitfield access)
3910{
Corentin Walleze4477002017-12-01 14:39:58 -05003911 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003913 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 return false;
3915 }
3916
Brandon Jones6cad5662017-06-14 13:25:13 -07003917 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003918 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003919 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3920 return false;
3921 }
3922
3923 if (length < 0)
3924 {
3925 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003926 return false;
3927 }
3928
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003929 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003930
3931 if (!buffer)
3932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003933 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003934 return false;
3935 }
3936
3937 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003938 CheckedNumeric<size_t> checkedOffset(offset);
3939 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003940
Jamie Madille2e406c2016-06-02 13:04:10 -04003941 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003943 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003944 return false;
3945 }
3946
3947 // Check for invalid bits in the mask
3948 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3949 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3950 GL_MAP_UNSYNCHRONIZED_BIT;
3951
3952 if (access & ~(allAccessBits))
3953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003954 context->handleError(InvalidValue()
3955 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003956 return false;
3957 }
3958
3959 if (length == 0)
3960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003961 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003962 return false;
3963 }
3964
3965 if (buffer->isMapped())
3966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003967 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003968 return false;
3969 }
3970
3971 // Check for invalid bit combinations
3972 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003974 context->handleError(InvalidOperation()
3975 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003976 return false;
3977 }
3978
3979 GLbitfield writeOnlyBits =
3980 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3981
3982 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003984 context->handleError(InvalidOperation()
3985 << "Invalid access bits when mapping buffer for reading: 0x"
3986 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003987 return false;
3988 }
3989
3990 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003992 context->handleError(
3993 InvalidOperation()
3994 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003995 return false;
3996 }
Geoff Lang79f71042017-08-14 16:43:43 -04003997
3998 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003999}
4000
4001bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004002 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03004003 GLintptr offset,
4004 GLsizeiptr length)
4005{
Brandon Jones6cad5662017-06-14 13:25:13 -07004006 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03004007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004008 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
4009 return false;
4010 }
4011
4012 if (length < 0)
4013 {
4014 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03004015 return false;
4016 }
4017
Corentin Walleze4477002017-12-01 14:39:58 -05004018 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03004019 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004020 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03004021 return false;
4022 }
4023
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004024 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004025
4026 if (buffer == nullptr)
4027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004028 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004029 return false;
4030 }
4031
4032 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004034 context->handleError(InvalidOperation()
4035 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004036 return false;
4037 }
4038
4039 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004040 CheckedNumeric<size_t> checkedOffset(offset);
4041 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004042
Jamie Madille2e406c2016-06-02 13:04:10 -04004043 if (!checkedSize.IsValid() ||
4044 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004046 context->handleError(InvalidValue()
4047 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004048 return false;
4049 }
4050
4051 return true;
4052}
4053
Olli Etuaho41997e72016-03-10 13:38:39 +02004054bool ValidateGenOrDelete(Context *context, GLint n)
4055{
4056 if (n < 0)
4057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004058 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004059 return false;
4060 }
4061 return true;
4062}
4063
Jamie Madill5b772312018-03-08 20:28:32 -05004064bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004065{
4066 if (!context->getExtensions().robustClientMemory)
4067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004068 context->handleError(InvalidOperation()
4069 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004070 return false;
4071 }
4072
4073 if (bufSize < 0)
4074 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004075 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004076 return false;
4077 }
4078
4079 return true;
4080}
4081
Jamie Madill5b772312018-03-08 20:28:32 -05004082bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004083{
4084 if (bufSize < numParams)
4085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004086 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4087 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004088 return false;
4089 }
4090
4091 return true;
4092}
4093
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004094bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004095 GLenum target,
4096 GLenum attachment,
4097 GLenum pname,
4098 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004099{
Geoff Lange8afa902017-09-27 15:00:43 -04004100 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004102 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004103 return false;
4104 }
4105
4106 int clientVersion = context->getClientMajorVersion();
4107
4108 switch (pname)
4109 {
4110 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4111 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4112 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4113 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4114 break;
4115
Martin Radeve5285d22017-07-14 16:23:53 +03004116 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4117 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4118 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4119 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4120 if (clientVersion < 3 || !context->getExtensions().multiview)
4121 {
4122 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4123 return false;
4124 }
4125 break;
4126
Geoff Langff5b2d52016-09-07 11:32:23 -04004127 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4128 if (clientVersion < 3 && !context->getExtensions().sRGB)
4129 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004130 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004131 return false;
4132 }
4133 break;
4134
4135 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4136 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4137 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4138 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4139 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4140 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4141 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4142 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4143 if (clientVersion < 3)
4144 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004145 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 return false;
4147 }
4148 break;
4149
Jiawei Shaoa8802472018-05-28 11:17:47 +08004150 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4151 if (!context->getExtensions().geometryShader)
4152 {
4153 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4154 return false;
4155 }
4156 break;
4157
Geoff Langff5b2d52016-09-07 11:32:23 -04004158 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004159 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004160 return false;
4161 }
4162
4163 // Determine if the attachment is a valid enum
4164 switch (attachment)
4165 {
4166 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004167 case GL_DEPTH:
4168 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004169 if (clientVersion < 3)
4170 {
Geoff Langfa125c92017-10-24 13:01:46 -04004171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004172 return false;
4173 }
4174 break;
4175
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004176 case GL_DEPTH_STENCIL_ATTACHMENT:
4177 if (clientVersion < 3 && !context->isWebGL1())
4178 {
4179 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4180 return false;
4181 }
4182 break;
4183
Geoff Langfa125c92017-10-24 13:01:46 -04004184 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004185 case GL_DEPTH_ATTACHMENT:
4186 case GL_STENCIL_ATTACHMENT:
4187 break;
4188
4189 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004190 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4191 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004192 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4193 {
Geoff Langfa125c92017-10-24 13:01:46 -04004194 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004195 return false;
4196 }
4197 break;
4198 }
4199
4200 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4201 ASSERT(framebuffer);
4202
4203 if (framebuffer->id() == 0)
4204 {
4205 if (clientVersion < 3)
4206 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004207 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004208 return false;
4209 }
4210
4211 switch (attachment)
4212 {
4213 case GL_BACK:
4214 case GL_DEPTH:
4215 case GL_STENCIL:
4216 break;
4217
4218 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004220 return false;
4221 }
4222 }
4223 else
4224 {
4225 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4226 {
4227 // Valid attachment query
4228 }
4229 else
4230 {
4231 switch (attachment)
4232 {
4233 case GL_DEPTH_ATTACHMENT:
4234 case GL_STENCIL_ATTACHMENT:
4235 break;
4236
4237 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004238 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004239 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004240 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004241 return false;
4242 }
4243 break;
4244
4245 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004246 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004247 return false;
4248 }
4249 }
4250 }
4251
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004252 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004253 if (attachmentObject)
4254 {
4255 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4256 attachmentObject->type() == GL_TEXTURE ||
4257 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4258
4259 switch (pname)
4260 {
4261 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4262 if (attachmentObject->type() != GL_RENDERBUFFER &&
4263 attachmentObject->type() != GL_TEXTURE)
4264 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004265 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004266 return false;
4267 }
4268 break;
4269
4270 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4271 if (attachmentObject->type() != GL_TEXTURE)
4272 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004273 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004274 return false;
4275 }
4276 break;
4277
4278 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4279 if (attachmentObject->type() != GL_TEXTURE)
4280 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004281 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004282 return false;
4283 }
4284 break;
4285
4286 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4287 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4288 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004289 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004290 return false;
4291 }
4292 break;
4293
4294 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4295 if (attachmentObject->type() != GL_TEXTURE)
4296 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004297 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004298 return false;
4299 }
4300 break;
4301
4302 default:
4303 break;
4304 }
4305 }
4306 else
4307 {
4308 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4309 // is NONE, then querying any other pname will generate INVALID_ENUM.
4310
4311 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4312 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4313 // INVALID_OPERATION for all other pnames
4314
4315 switch (pname)
4316 {
4317 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4318 break;
4319
4320 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4321 if (clientVersion < 3)
4322 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004323 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004324 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004325 return false;
4326 }
4327 break;
4328
4329 default:
4330 if (clientVersion < 3)
4331 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004332 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004333 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004334 return false;
4335 }
4336 else
4337 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004338 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004339 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004340 return false;
4341 }
4342 }
4343 }
4344
Martin Radeve5285d22017-07-14 16:23:53 +03004345 if (numParams)
4346 {
4347 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4348 {
4349 // Only when the viewport offsets are queried we can have a varying number of output
4350 // parameters.
4351 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4352 *numParams = numViews * 2;
4353 }
4354 else
4355 {
4356 // For all other queries we can have only one output parameter.
4357 *numParams = 1;
4358 }
4359 }
4360
Geoff Langff5b2d52016-09-07 11:32:23 -04004361 return true;
4362}
4363
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004364bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004365 GLenum target,
4366 GLenum attachment,
4367 GLenum pname,
4368 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004369 GLsizei *length,
4370 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004371{
4372 if (!ValidateRobustEntryPoint(context, bufSize))
4373 {
4374 return false;
4375 }
4376
Brandon Jonesd1049182018-03-28 10:02:20 -07004377 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004378 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004379 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004380 {
4381 return false;
4382 }
4383
Brandon Jonesd1049182018-03-28 10:02:20 -07004384 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004385 {
4386 return false;
4387 }
4388
Brandon Jonesd1049182018-03-28 10:02:20 -07004389 SetRobustLengthParam(length, numParams);
4390
Geoff Langff5b2d52016-09-07 11:32:23 -04004391 return true;
4392}
4393
Jamie Madill5b772312018-03-08 20:28:32 -05004394bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004395 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004396 GLenum pname,
4397 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004398 GLsizei *length,
4399 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004400{
4401 if (!ValidateRobustEntryPoint(context, bufSize))
4402 {
4403 return false;
4404 }
4405
Brandon Jonesd1049182018-03-28 10:02:20 -07004406 GLsizei numParams = 0;
4407
4408 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004409 {
4410 return false;
4411 }
4412
Brandon Jonesd1049182018-03-28 10:02:20 -07004413 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004414 {
4415 return false;
4416 }
4417
Brandon Jonesd1049182018-03-28 10:02:20 -07004418 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004419 return true;
4420}
4421
Jamie Madill5b772312018-03-08 20:28:32 -05004422bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004423 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004424 GLenum pname,
4425 GLsizei bufSize,
4426 GLsizei *length,
4427 GLint64 *params)
4428{
Brandon Jonesd1049182018-03-28 10:02:20 -07004429 GLsizei numParams = 0;
4430
Geoff Langebebe1c2016-10-14 12:01:31 -04004431 if (!ValidateRobustEntryPoint(context, bufSize))
4432 {
4433 return false;
4434 }
4435
Brandon Jonesd1049182018-03-28 10:02:20 -07004436 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004437 {
4438 return false;
4439 }
4440
Brandon Jonesd1049182018-03-28 10:02:20 -07004441 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004442 {
4443 return false;
4444 }
4445
Brandon Jonesd1049182018-03-28 10:02:20 -07004446 SetRobustLengthParam(length, numParams);
4447
Geoff Langff5b2d52016-09-07 11:32:23 -04004448 return true;
4449}
4450
Jamie Madill5b772312018-03-08 20:28:32 -05004451bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004452{
4453 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004454 if (numParams)
4455 {
4456 *numParams = 1;
4457 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004458
4459 Program *programObject = GetValidProgram(context, program);
4460 if (!programObject)
4461 {
4462 return false;
4463 }
4464
4465 switch (pname)
4466 {
4467 case GL_DELETE_STATUS:
4468 case GL_LINK_STATUS:
4469 case GL_VALIDATE_STATUS:
4470 case GL_INFO_LOG_LENGTH:
4471 case GL_ATTACHED_SHADERS:
4472 case GL_ACTIVE_ATTRIBUTES:
4473 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4474 case GL_ACTIVE_UNIFORMS:
4475 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4476 break;
4477
4478 case GL_PROGRAM_BINARY_LENGTH:
4479 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004481 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4482 "requires GL_OES_get_program_binary or "
4483 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004484 return false;
4485 }
4486 break;
4487
4488 case GL_ACTIVE_UNIFORM_BLOCKS:
4489 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4490 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4491 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4492 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4493 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4494 if (context->getClientMajorVersion() < 3)
4495 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004496 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004497 return false;
4498 }
4499 break;
4500
Yunchao He61afff12017-03-14 15:34:03 +08004501 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004502 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004503 if (context->getClientVersion() < Version(3, 1))
4504 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004505 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004506 return false;
4507 }
4508 break;
4509
Jiawei Shao6ae51612018-02-23 14:03:25 +08004510 case GL_COMPUTE_WORK_GROUP_SIZE:
4511 if (context->getClientVersion() < Version(3, 1))
4512 {
4513 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4514 return false;
4515 }
4516
4517 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4518 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4519 // program which has not been linked successfully, or which does not contain objects to
4520 // form a compute shader.
4521 if (!programObject->isLinked())
4522 {
4523 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4524 return false;
4525 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004526 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004527 {
4528 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4529 return false;
4530 }
4531 break;
4532
Jiawei Shao447bfac2018-03-14 14:23:40 +08004533 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4534 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4535 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4536 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4537 if (!context->getExtensions().geometryShader)
4538 {
4539 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4540 return false;
4541 }
4542
4543 // [EXT_geometry_shader] Chapter 7.12
4544 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4545 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4546 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4547 // successfully, or which does not contain objects to form a geometry shader.
4548 if (!programObject->isLinked())
4549 {
4550 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4551 return false;
4552 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004553 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004554 {
4555 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4556 return false;
4557 }
4558 break;
4559
Geoff Langff5b2d52016-09-07 11:32:23 -04004560 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004561 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004562 return false;
4563 }
4564
4565 return true;
4566}
4567
4568bool ValidateGetProgramivRobustANGLE(Context *context,
4569 GLuint program,
4570 GLenum pname,
4571 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004572 GLsizei *length,
4573 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004574{
4575 if (!ValidateRobustEntryPoint(context, bufSize))
4576 {
4577 return false;
4578 }
4579
Brandon Jonesd1049182018-03-28 10:02:20 -07004580 GLsizei numParams = 0;
4581
4582 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004583 {
4584 return false;
4585 }
4586
Brandon Jonesd1049182018-03-28 10:02:20 -07004587 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004588 {
4589 return false;
4590 }
4591
Brandon Jonesd1049182018-03-28 10:02:20 -07004592 SetRobustLengthParam(length, numParams);
4593
Geoff Langff5b2d52016-09-07 11:32:23 -04004594 return true;
4595}
4596
Geoff Lang740d9022016-10-07 11:20:52 -04004597bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4598 GLenum target,
4599 GLenum pname,
4600 GLsizei bufSize,
4601 GLsizei *length,
4602 GLint *params)
4603{
4604 if (!ValidateRobustEntryPoint(context, bufSize))
4605 {
4606 return false;
4607 }
4608
Brandon Jonesd1049182018-03-28 10:02:20 -07004609 GLsizei numParams = 0;
4610
4611 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004612 {
4613 return false;
4614 }
4615
Brandon Jonesd1049182018-03-28 10:02:20 -07004616 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004617 {
4618 return false;
4619 }
4620
Brandon Jonesd1049182018-03-28 10:02:20 -07004621 SetRobustLengthParam(length, numParams);
4622
Geoff Lang740d9022016-10-07 11:20:52 -04004623 return true;
4624}
4625
Geoff Langd7d0ed32016-10-07 11:33:51 -04004626bool ValidateGetShaderivRobustANGLE(Context *context,
4627 GLuint shader,
4628 GLenum pname,
4629 GLsizei bufSize,
4630 GLsizei *length,
4631 GLint *params)
4632{
4633 if (!ValidateRobustEntryPoint(context, bufSize))
4634 {
4635 return false;
4636 }
4637
Brandon Jonesd1049182018-03-28 10:02:20 -07004638 GLsizei numParams = 0;
4639
4640 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004641 {
4642 return false;
4643 }
4644
Brandon Jonesd1049182018-03-28 10:02:20 -07004645 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004646 {
4647 return false;
4648 }
4649
Brandon Jonesd1049182018-03-28 10:02:20 -07004650 SetRobustLengthParam(length, numParams);
4651
Geoff Langd7d0ed32016-10-07 11:33:51 -04004652 return true;
4653}
4654
Geoff Langc1984ed2016-10-07 12:41:00 -04004655bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004656 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004657 GLenum pname,
4658 GLsizei bufSize,
4659 GLsizei *length,
4660 GLfloat *params)
4661{
4662 if (!ValidateRobustEntryPoint(context, bufSize))
4663 {
4664 return false;
4665 }
4666
Brandon Jonesd1049182018-03-28 10:02:20 -07004667 GLsizei numParams = 0;
4668
4669 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004670 {
4671 return false;
4672 }
4673
Brandon Jonesd1049182018-03-28 10:02:20 -07004674 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004675 {
4676 return false;
4677 }
4678
Brandon Jonesd1049182018-03-28 10:02:20 -07004679 SetRobustLengthParam(length, numParams);
4680
Geoff Langc1984ed2016-10-07 12:41:00 -04004681 return true;
4682}
4683
Geoff Langc1984ed2016-10-07 12:41:00 -04004684bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004685 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004686 GLenum pname,
4687 GLsizei bufSize,
4688 GLsizei *length,
4689 GLint *params)
4690{
Brandon Jonesd1049182018-03-28 10:02:20 -07004691
Geoff Langc1984ed2016-10-07 12:41:00 -04004692 if (!ValidateRobustEntryPoint(context, bufSize))
4693 {
4694 return false;
4695 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004696 GLsizei numParams = 0;
4697 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004698 {
4699 return false;
4700 }
4701
Brandon Jonesd1049182018-03-28 10:02:20 -07004702 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004703 {
4704 return false;
4705 }
4706
Brandon Jonesd1049182018-03-28 10:02:20 -07004707 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004708 return true;
4709}
4710
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004711bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4712 TextureType target,
4713 GLenum pname,
4714 GLsizei bufSize,
4715 GLsizei *length,
4716 GLint *params)
4717{
4718 UNIMPLEMENTED();
4719 return false;
4720}
4721
4722bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4723 TextureType target,
4724 GLenum pname,
4725 GLsizei bufSize,
4726 GLsizei *length,
4727 GLuint *params)
4728{
4729 UNIMPLEMENTED();
4730 return false;
4731}
4732
Geoff Langc1984ed2016-10-07 12:41:00 -04004733bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004734 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004735 GLenum pname,
4736 GLsizei bufSize,
4737 const GLfloat *params)
4738{
4739 if (!ValidateRobustEntryPoint(context, bufSize))
4740 {
4741 return false;
4742 }
4743
4744 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4745}
4746
Geoff Langc1984ed2016-10-07 12:41:00 -04004747bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004748 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004749 GLenum pname,
4750 GLsizei bufSize,
4751 const GLint *params)
4752{
4753 if (!ValidateRobustEntryPoint(context, bufSize))
4754 {
4755 return false;
4756 }
4757
4758 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4759}
4760
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004761bool ValidateTexParameterIivRobustANGLE(Context *context,
4762 TextureType target,
4763 GLenum pname,
4764 GLsizei bufSize,
4765 const GLint *params)
4766{
4767 UNIMPLEMENTED();
4768 return false;
4769}
4770
4771bool ValidateTexParameterIuivRobustANGLE(Context *context,
4772 TextureType target,
4773 GLenum pname,
4774 GLsizei bufSize,
4775 const GLuint *params)
4776{
4777 UNIMPLEMENTED();
4778 return false;
4779}
4780
Geoff Langc1984ed2016-10-07 12:41:00 -04004781bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4782 GLuint sampler,
4783 GLenum pname,
4784 GLuint bufSize,
4785 GLsizei *length,
4786 GLfloat *params)
4787{
4788 if (!ValidateRobustEntryPoint(context, bufSize))
4789 {
4790 return false;
4791 }
4792
Brandon Jonesd1049182018-03-28 10:02:20 -07004793 GLsizei numParams = 0;
4794
4795 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004796 {
4797 return false;
4798 }
4799
Brandon Jonesd1049182018-03-28 10:02:20 -07004800 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004801 {
4802 return false;
4803 }
4804
Brandon Jonesd1049182018-03-28 10:02:20 -07004805 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004806 return true;
4807}
4808
Geoff Langc1984ed2016-10-07 12:41:00 -04004809bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4810 GLuint sampler,
4811 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004812 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004813 GLsizei *length,
4814 GLint *params)
4815{
4816 if (!ValidateRobustEntryPoint(context, bufSize))
4817 {
4818 return false;
4819 }
4820
Brandon Jonesd1049182018-03-28 10:02:20 -07004821 GLsizei numParams = 0;
4822
4823 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004824 {
4825 return false;
4826 }
4827
Brandon Jonesd1049182018-03-28 10:02:20 -07004828 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004829 {
4830 return false;
4831 }
4832
Brandon Jonesd1049182018-03-28 10:02:20 -07004833 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004834 return true;
4835}
4836
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004837bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4838 GLuint sampler,
4839 GLenum pname,
4840 GLsizei bufSize,
4841 GLsizei *length,
4842 GLint *params)
4843{
4844 UNIMPLEMENTED();
4845 return false;
4846}
4847
4848bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4849 GLuint sampler,
4850 GLenum pname,
4851 GLsizei bufSize,
4852 GLsizei *length,
4853 GLuint *params)
4854{
4855 UNIMPLEMENTED();
4856 return false;
4857}
4858
Geoff Langc1984ed2016-10-07 12:41:00 -04004859bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4860 GLuint sampler,
4861 GLenum pname,
4862 GLsizei bufSize,
4863 const GLfloat *params)
4864{
4865 if (!ValidateRobustEntryPoint(context, bufSize))
4866 {
4867 return false;
4868 }
4869
4870 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4871}
4872
Geoff Langc1984ed2016-10-07 12:41:00 -04004873bool ValidateSamplerParameterivRobustANGLE(Context *context,
4874 GLuint sampler,
4875 GLenum pname,
4876 GLsizei bufSize,
4877 const GLint *params)
4878{
4879 if (!ValidateRobustEntryPoint(context, bufSize))
4880 {
4881 return false;
4882 }
4883
4884 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4885}
4886
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004887bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4888 GLuint sampler,
4889 GLenum pname,
4890 GLsizei bufSize,
4891 const GLint *param)
4892{
4893 UNIMPLEMENTED();
4894 return false;
4895}
4896
4897bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4898 GLuint sampler,
4899 GLenum pname,
4900 GLsizei bufSize,
4901 const GLuint *param)
4902{
4903 UNIMPLEMENTED();
4904 return false;
4905}
4906
Geoff Lang0b031062016-10-13 14:30:04 -04004907bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4908 GLuint index,
4909 GLenum pname,
4910 GLsizei bufSize,
4911 GLsizei *length,
4912 GLfloat *params)
4913{
4914 if (!ValidateRobustEntryPoint(context, bufSize))
4915 {
4916 return false;
4917 }
4918
Brandon Jonesd1049182018-03-28 10:02:20 -07004919 GLsizei writeLength = 0;
4920
4921 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004922 {
4923 return false;
4924 }
4925
Brandon Jonesd1049182018-03-28 10:02:20 -07004926 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004927 {
4928 return false;
4929 }
4930
Brandon Jonesd1049182018-03-28 10:02:20 -07004931 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004932 return true;
4933}
4934
Geoff Lang0b031062016-10-13 14:30:04 -04004935bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4936 GLuint index,
4937 GLenum pname,
4938 GLsizei bufSize,
4939 GLsizei *length,
4940 GLint *params)
4941{
4942 if (!ValidateRobustEntryPoint(context, bufSize))
4943 {
4944 return false;
4945 }
4946
Brandon Jonesd1049182018-03-28 10:02:20 -07004947 GLsizei writeLength = 0;
4948
4949 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004950 {
4951 return false;
4952 }
4953
Brandon Jonesd1049182018-03-28 10:02:20 -07004954 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004955 {
4956 return false;
4957 }
4958
Brandon Jonesd1049182018-03-28 10:02:20 -07004959 SetRobustLengthParam(length, writeLength);
4960
Geoff Lang0b031062016-10-13 14:30:04 -04004961 return true;
4962}
4963
Geoff Lang0b031062016-10-13 14:30:04 -04004964bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4965 GLuint index,
4966 GLenum pname,
4967 GLsizei bufSize,
4968 GLsizei *length,
4969 void **pointer)
4970{
4971 if (!ValidateRobustEntryPoint(context, bufSize))
4972 {
4973 return false;
4974 }
4975
Brandon Jonesd1049182018-03-28 10:02:20 -07004976 GLsizei writeLength = 0;
4977
4978 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004979 {
4980 return false;
4981 }
4982
Brandon Jonesd1049182018-03-28 10:02:20 -07004983 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004984 {
4985 return false;
4986 }
4987
Brandon Jonesd1049182018-03-28 10:02:20 -07004988 SetRobustLengthParam(length, writeLength);
4989
Geoff Lang0b031062016-10-13 14:30:04 -04004990 return true;
4991}
4992
Geoff Lang0b031062016-10-13 14:30:04 -04004993bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4994 GLuint index,
4995 GLenum pname,
4996 GLsizei bufSize,
4997 GLsizei *length,
4998 GLint *params)
4999{
5000 if (!ValidateRobustEntryPoint(context, bufSize))
5001 {
5002 return false;
5003 }
5004
Brandon Jonesd1049182018-03-28 10:02:20 -07005005 GLsizei writeLength = 0;
5006
5007 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005008 {
5009 return false;
5010 }
5011
Brandon Jonesd1049182018-03-28 10:02:20 -07005012 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005013 {
5014 return false;
5015 }
5016
Brandon Jonesd1049182018-03-28 10:02:20 -07005017 SetRobustLengthParam(length, writeLength);
5018
Geoff Lang0b031062016-10-13 14:30:04 -04005019 return true;
5020}
5021
Geoff Lang0b031062016-10-13 14:30:04 -04005022bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5023 GLuint index,
5024 GLenum pname,
5025 GLsizei bufSize,
5026 GLsizei *length,
5027 GLuint *params)
5028{
5029 if (!ValidateRobustEntryPoint(context, bufSize))
5030 {
5031 return false;
5032 }
5033
Brandon Jonesd1049182018-03-28 10:02:20 -07005034 GLsizei writeLength = 0;
5035
5036 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005037 {
5038 return false;
5039 }
5040
Brandon Jonesd1049182018-03-28 10:02:20 -07005041 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005042 {
5043 return false;
5044 }
5045
Brandon Jonesd1049182018-03-28 10:02:20 -07005046 SetRobustLengthParam(length, writeLength);
5047
Geoff Lang0b031062016-10-13 14:30:04 -04005048 return true;
5049}
5050
Geoff Lang6899b872016-10-14 11:30:13 -04005051bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5052 GLuint program,
5053 GLuint uniformBlockIndex,
5054 GLenum pname,
5055 GLsizei bufSize,
5056 GLsizei *length,
5057 GLint *params)
5058{
5059 if (!ValidateRobustEntryPoint(context, bufSize))
5060 {
5061 return false;
5062 }
5063
Brandon Jonesd1049182018-03-28 10:02:20 -07005064 GLsizei writeLength = 0;
5065
5066 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5067 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005068 {
5069 return false;
5070 }
5071
Brandon Jonesd1049182018-03-28 10:02:20 -07005072 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005073 {
5074 return false;
5075 }
5076
Brandon Jonesd1049182018-03-28 10:02:20 -07005077 SetRobustLengthParam(length, writeLength);
5078
Geoff Lang6899b872016-10-14 11:30:13 -04005079 return true;
5080}
5081
Brandon Jones416aaf92018-04-10 08:10:16 -07005082bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005083 GLenum target,
5084 GLenum internalformat,
5085 GLenum pname,
5086 GLsizei bufSize,
5087 GLsizei *length,
5088 GLint *params)
5089{
5090 if (!ValidateRobustEntryPoint(context, bufSize))
5091 {
5092 return false;
5093 }
5094
Brandon Jonesd1049182018-03-28 10:02:20 -07005095 GLsizei numParams = 0;
5096
5097 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5098 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005099 {
5100 return false;
5101 }
5102
Brandon Jonesd1049182018-03-28 10:02:20 -07005103 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005104 {
5105 return false;
5106 }
5107
Brandon Jonesd1049182018-03-28 10:02:20 -07005108 SetRobustLengthParam(length, numParams);
5109
Geoff Lang0a9661f2016-10-20 10:59:20 -07005110 return true;
5111}
5112
Jamie Madill5b772312018-03-08 20:28:32 -05005113bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005114 GLuint attribIndex,
5115 GLint size,
5116 GLenum type,
5117 GLboolean pureInteger)
5118{
5119 const Caps &caps = context->getCaps();
5120 if (attribIndex >= caps.maxVertexAttributes)
5121 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005122 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005123 return false;
5124 }
5125
5126 if (size < 1 || size > 4)
5127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005128 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005129 return false;
Shao80957d92017-02-20 21:25:59 +08005130 }
5131
5132 switch (type)
5133 {
5134 case GL_BYTE:
5135 case GL_UNSIGNED_BYTE:
5136 case GL_SHORT:
5137 case GL_UNSIGNED_SHORT:
5138 break;
5139
5140 case GL_INT:
5141 case GL_UNSIGNED_INT:
5142 if (context->getClientMajorVersion() < 3)
5143 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005144 context->handleError(InvalidEnum()
5145 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005146 return false;
5147 }
5148 break;
5149
5150 case GL_FIXED:
5151 case GL_FLOAT:
5152 if (pureInteger)
5153 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005154 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005155 return false;
5156 }
5157 break;
5158
5159 case GL_HALF_FLOAT:
5160 if (context->getClientMajorVersion() < 3)
5161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005162 context->handleError(InvalidEnum()
5163 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005164 return false;
5165 }
5166 if (pureInteger)
5167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005169 return false;
5170 }
5171 break;
5172
5173 case GL_INT_2_10_10_10_REV:
5174 case GL_UNSIGNED_INT_2_10_10_10_REV:
5175 if (context->getClientMajorVersion() < 3)
5176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005177 context->handleError(InvalidEnum()
5178 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005179 return false;
5180 }
5181 if (pureInteger)
5182 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005183 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005184 return false;
5185 }
5186 if (size != 4)
5187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005188 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5189 "UNSIGNED_INT_2_10_10_10_REV and "
5190 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005191 return false;
5192 }
5193 break;
5194
5195 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005197 return false;
5198 }
5199
5200 return true;
5201}
5202
Geoff Lang76e65652017-03-27 14:58:02 -04005203// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5204// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5205// specified clear value and the type of a buffer that is being cleared generates an
5206// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005207bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005208 GLint drawbuffer,
5209 const GLenum *validComponentTypes,
5210 size_t validComponentTypeCount)
5211{
5212 const FramebufferAttachment *attachment =
5213 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5214 if (attachment)
5215 {
5216 GLenum componentType = attachment->getFormat().info->componentType;
5217 const GLenum *end = validComponentTypes + validComponentTypeCount;
5218 if (std::find(validComponentTypes, end, componentType) == end)
5219 {
5220 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005221 InvalidOperation()
5222 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005223 return false;
5224 }
5225 }
5226
5227 return true;
5228}
5229
Jamie Madill5b772312018-03-08 20:28:32 -05005230bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005231{
5232 if (!ValidateRobustEntryPoint(context, dataSize))
5233 {
5234 return false;
5235 }
5236
Corentin Wallez336129f2017-10-17 15:55:40 -04005237 gl::Buffer *pixelUnpackBuffer =
5238 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005239 if (pixelUnpackBuffer == nullptr)
5240 {
5241 if (dataSize < imageSize)
5242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005243 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005244 }
5245 }
5246 return true;
5247}
5248
Jamie Madill5b772312018-03-08 20:28:32 -05005249bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005250 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005251 GLenum pname,
5252 bool pointerVersion,
5253 GLsizei *numParams)
5254{
5255 if (numParams)
5256 {
5257 *numParams = 0;
5258 }
5259
Corentin Walleze4477002017-12-01 14:39:58 -05005260 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005262 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005263 return false;
5264 }
5265
5266 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5267 if (!buffer)
5268 {
5269 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005271 return false;
5272 }
5273
5274 const Extensions &extensions = context->getExtensions();
5275
5276 switch (pname)
5277 {
5278 case GL_BUFFER_USAGE:
5279 case GL_BUFFER_SIZE:
5280 break;
5281
5282 case GL_BUFFER_ACCESS_OES:
5283 if (!extensions.mapBuffer)
5284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005285 context->handleError(InvalidEnum()
5286 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005287 return false;
5288 }
5289 break;
5290
5291 case GL_BUFFER_MAPPED:
5292 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5293 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5294 !extensions.mapBufferRange)
5295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005296 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5297 "GL_OES_mapbuffer or "
5298 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005299 return false;
5300 }
5301 break;
5302
5303 case GL_BUFFER_MAP_POINTER:
5304 if (!pointerVersion)
5305 {
5306 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005307 InvalidEnum()
5308 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005309 return false;
5310 }
5311 break;
5312
5313 case GL_BUFFER_ACCESS_FLAGS:
5314 case GL_BUFFER_MAP_OFFSET:
5315 case GL_BUFFER_MAP_LENGTH:
5316 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005318 context->handleError(InvalidEnum()
5319 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005320 return false;
5321 }
5322 break;
5323
5324 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005325 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005326 return false;
5327 }
5328
5329 // All buffer parameter queries return one value.
5330 if (numParams)
5331 {
5332 *numParams = 1;
5333 }
5334
5335 return true;
5336}
5337
5338bool ValidateGetRenderbufferParameterivBase(Context *context,
5339 GLenum target,
5340 GLenum pname,
5341 GLsizei *length)
5342{
5343 if (length)
5344 {
5345 *length = 0;
5346 }
5347
5348 if (target != GL_RENDERBUFFER)
5349 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005350 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005351 return false;
5352 }
5353
5354 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5355 if (renderbuffer == nullptr)
5356 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005357 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005358 return false;
5359 }
5360
5361 switch (pname)
5362 {
5363 case GL_RENDERBUFFER_WIDTH:
5364 case GL_RENDERBUFFER_HEIGHT:
5365 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5366 case GL_RENDERBUFFER_RED_SIZE:
5367 case GL_RENDERBUFFER_GREEN_SIZE:
5368 case GL_RENDERBUFFER_BLUE_SIZE:
5369 case GL_RENDERBUFFER_ALPHA_SIZE:
5370 case GL_RENDERBUFFER_DEPTH_SIZE:
5371 case GL_RENDERBUFFER_STENCIL_SIZE:
5372 break;
5373
5374 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5375 if (!context->getExtensions().framebufferMultisample)
5376 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 return false;
5379 }
5380 break;
5381
5382 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005383 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005384 return false;
5385 }
5386
5387 if (length)
5388 {
5389 *length = 1;
5390 }
5391 return true;
5392}
5393
5394bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5395{
5396 if (length)
5397 {
5398 *length = 0;
5399 }
5400
5401 if (GetValidShader(context, shader) == nullptr)
5402 {
5403 return false;
5404 }
5405
5406 switch (pname)
5407 {
5408 case GL_SHADER_TYPE:
5409 case GL_DELETE_STATUS:
5410 case GL_COMPILE_STATUS:
5411 case GL_INFO_LOG_LENGTH:
5412 case GL_SHADER_SOURCE_LENGTH:
5413 break;
5414
5415 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5416 if (!context->getExtensions().translatedShaderSource)
5417 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005418 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005419 return false;
5420 }
5421 break;
5422
5423 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005424 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005425 return false;
5426 }
5427
5428 if (length)
5429 {
5430 *length = 1;
5431 }
5432 return true;
5433}
5434
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005435bool ValidateGetTexParameterBase(Context *context,
5436 TextureType target,
5437 GLenum pname,
5438 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005439{
5440 if (length)
5441 {
5442 *length = 0;
5443 }
5444
5445 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5446 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005447 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005448 return false;
5449 }
5450
5451 if (context->getTargetTexture(target) == nullptr)
5452 {
5453 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005454 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005455 return false;
5456 }
5457
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005458 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5459 {
5460 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5461 return false;
5462 }
5463
Jamie Madillbe849e42017-05-02 15:49:00 -04005464 switch (pname)
5465 {
5466 case GL_TEXTURE_MAG_FILTER:
5467 case GL_TEXTURE_MIN_FILTER:
5468 case GL_TEXTURE_WRAP_S:
5469 case GL_TEXTURE_WRAP_T:
5470 break;
5471
5472 case GL_TEXTURE_USAGE_ANGLE:
5473 if (!context->getExtensions().textureUsage)
5474 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005475 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005476 return false;
5477 }
5478 break;
5479
5480 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005481 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005482 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005483 return false;
5484 }
5485 break;
5486
5487 case GL_TEXTURE_IMMUTABLE_FORMAT:
5488 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5489 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005490 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005491 return false;
5492 }
5493 break;
5494
5495 case GL_TEXTURE_WRAP_R:
5496 case GL_TEXTURE_IMMUTABLE_LEVELS:
5497 case GL_TEXTURE_SWIZZLE_R:
5498 case GL_TEXTURE_SWIZZLE_G:
5499 case GL_TEXTURE_SWIZZLE_B:
5500 case GL_TEXTURE_SWIZZLE_A:
5501 case GL_TEXTURE_BASE_LEVEL:
5502 case GL_TEXTURE_MAX_LEVEL:
5503 case GL_TEXTURE_MIN_LOD:
5504 case GL_TEXTURE_MAX_LOD:
5505 case GL_TEXTURE_COMPARE_MODE:
5506 case GL_TEXTURE_COMPARE_FUNC:
5507 if (context->getClientMajorVersion() < 3)
5508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005509 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005510 return false;
5511 }
5512 break;
5513
5514 case GL_TEXTURE_SRGB_DECODE_EXT:
5515 if (!context->getExtensions().textureSRGBDecode)
5516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005517 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005518 return false;
5519 }
5520 break;
5521
Yunchao Hebacaa712018-01-30 14:01:39 +08005522 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5523 if (context->getClientVersion() < Version(3, 1))
5524 {
5525 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5526 return false;
5527 }
5528 break;
5529
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005530 case GL_GENERATE_MIPMAP:
5531 case GL_TEXTURE_CROP_RECT_OES:
5532 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5533 // after GL_OES_draw_texture functionality implemented
5534 if (context->getClientMajorVersion() > 1)
5535 {
5536 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5537 return false;
5538 }
5539 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005540 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005541 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005542 return false;
5543 }
5544
5545 if (length)
5546 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005547 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005548 }
5549 return true;
5550}
5551
5552bool ValidateGetVertexAttribBase(Context *context,
5553 GLuint index,
5554 GLenum pname,
5555 GLsizei *length,
5556 bool pointer,
5557 bool pureIntegerEntryPoint)
5558{
5559 if (length)
5560 {
5561 *length = 0;
5562 }
5563
5564 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005566 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 return false;
5568 }
5569
5570 if (index >= context->getCaps().maxVertexAttributes)
5571 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005572 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005573 return false;
5574 }
5575
5576 if (pointer)
5577 {
5578 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5579 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005580 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005581 return false;
5582 }
5583 }
5584 else
5585 {
5586 switch (pname)
5587 {
5588 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5589 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5590 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5591 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5592 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5593 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5594 case GL_CURRENT_VERTEX_ATTRIB:
5595 break;
5596
5597 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5598 static_assert(
5599 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5600 "ANGLE extension enums not equal to GL enums.");
5601 if (context->getClientMajorVersion() < 3 &&
5602 !context->getExtensions().instancedArrays)
5603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005604 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5605 "requires OpenGL ES 3.0 or "
5606 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005607 return false;
5608 }
5609 break;
5610
5611 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5612 if (context->getClientMajorVersion() < 3)
5613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005614 context->handleError(
5615 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005616 return false;
5617 }
5618 break;
5619
5620 case GL_VERTEX_ATTRIB_BINDING:
5621 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5622 if (context->getClientVersion() < ES_3_1)
5623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005624 context->handleError(InvalidEnum()
5625 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005626 return false;
5627 }
5628 break;
5629
5630 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005631 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005632 return false;
5633 }
5634 }
5635
5636 if (length)
5637 {
5638 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5639 {
5640 *length = 4;
5641 }
5642 else
5643 {
5644 *length = 1;
5645 }
5646 }
5647
5648 return true;
5649}
5650
Jamie Madill4928b7c2017-06-20 12:57:39 -04005651bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005652 GLint x,
5653 GLint y,
5654 GLsizei width,
5655 GLsizei height,
5656 GLenum format,
5657 GLenum type,
5658 GLsizei bufSize,
5659 GLsizei *length,
5660 GLsizei *columns,
5661 GLsizei *rows,
5662 void *pixels)
5663{
5664 if (length != nullptr)
5665 {
5666 *length = 0;
5667 }
5668 if (rows != nullptr)
5669 {
5670 *rows = 0;
5671 }
5672 if (columns != nullptr)
5673 {
5674 *columns = 0;
5675 }
5676
5677 if (width < 0 || height < 0)
5678 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005679 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005680 return false;
5681 }
5682
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005683 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005684
Jamie Madill427064d2018-04-13 16:20:34 -04005685 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005686 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005687 return false;
5688 }
5689
Jamie Madille98b1b52018-03-08 09:47:23 -05005690 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005691 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005692 return false;
5693 }
5694
Jamie Madill690c8eb2018-03-12 15:20:03 -04005695 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005696 ASSERT(framebuffer);
5697
5698 if (framebuffer->getReadBufferState() == GL_NONE)
5699 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005700 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005701 return false;
5702 }
5703
5704 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5705 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5706 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5707 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5708 // situation is an application error that would lead to a crash in ANGLE.
5709 if (readBuffer == nullptr)
5710 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005711 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005712 return false;
5713 }
5714
Martin Radev28031682017-07-28 14:47:56 +03005715 // ANGLE_multiview, Revision 1:
5716 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005717 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5718 // in the current read framebuffer is more than one.
5719 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005720 {
5721 context->handleError(InvalidFramebufferOperation()
5722 << "Attempting to read from a multi-view framebuffer.");
5723 return false;
5724 }
5725
Geoff Lang280ba992017-04-18 16:30:58 -04005726 if (context->getExtensions().webglCompatibility)
5727 {
5728 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5729 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5730 // and type before validating the combination of format and type. However, the
5731 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5732 // verifies that GL_INVALID_OPERATION is generated.
5733 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5734 // dEQP/WebGL.
5735 if (!ValidReadPixelsFormatEnum(context, format))
5736 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005737 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005738 return false;
5739 }
5740
5741 if (!ValidReadPixelsTypeEnum(context, type))
5742 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005743 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005744 return false;
5745 }
5746 }
5747
Jamie Madill690c8eb2018-03-12 15:20:03 -04005748 GLenum currentFormat = GL_NONE;
5749 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5750
5751 GLenum currentType = GL_NONE;
5752 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5753
Jamie Madillbe849e42017-05-02 15:49:00 -04005754 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5755
5756 bool validFormatTypeCombination =
5757 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5758
5759 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5760 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005761 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005762 return false;
5763 }
5764
5765 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005766 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005767 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5768 {
5769 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005770 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005771 return false;
5772 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005773 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5774 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5775 {
5776 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5777 return false;
5778 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005779
5780 // .. the data would be packed to the buffer object such that the memory writes required
5781 // would exceed the data store size.
5782 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5783 const gl::Extents size(width, height, 1);
5784 const auto &pack = context->getGLState().getPackState();
5785
Jamie Madillca2ff382018-07-11 09:01:17 -04005786 GLuint endByte = 0;
5787 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005788 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005789 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005790 return false;
5791 }
5792
Jamie Madillbe849e42017-05-02 15:49:00 -04005793 if (bufSize >= 0)
5794 {
5795 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5796 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005797 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005798 return false;
5799 }
5800 }
5801
5802 if (pixelPackBuffer != nullptr)
5803 {
5804 CheckedNumeric<size_t> checkedEndByte(endByte);
5805 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5806 checkedEndByte += checkedOffset;
5807
5808 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5809 {
5810 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005811 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005812 return false;
5813 }
5814 }
5815
5816 if (pixelPackBuffer == nullptr && length != nullptr)
5817 {
5818 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5819 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005820 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005821 return false;
5822 }
5823
5824 *length = static_cast<GLsizei>(endByte);
5825 }
5826
Geoff Langa953b522018-02-21 16:56:23 -05005827 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005828 angle::CheckedNumeric<int> clippedExtent(length);
5829 if (start < 0)
5830 {
5831 // "subtract" the area that is less than 0
5832 clippedExtent += start;
5833 }
5834
Geoff Langa953b522018-02-21 16:56:23 -05005835 angle::CheckedNumeric<int> readExtent = start;
5836 readExtent += length;
5837 if (!readExtent.IsValid())
5838 {
5839 return false;
5840 }
5841
5842 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005843 {
5844 // Subtract the region to the right of the read buffer
5845 clippedExtent -= (readExtent - bufferSize);
5846 }
5847
5848 if (!clippedExtent.IsValid())
5849 {
Geoff Langa953b522018-02-21 16:56:23 -05005850 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005851 }
5852
Geoff Langa953b522018-02-21 16:56:23 -05005853 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5854 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005855 };
5856
Geoff Langa953b522018-02-21 16:56:23 -05005857 GLsizei writtenColumns = 0;
5858 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5859 {
5860 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5861 return false;
5862 }
5863
5864 GLsizei writtenRows = 0;
5865 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5866 {
5867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5868 return false;
5869 }
5870
Jamie Madillbe849e42017-05-02 15:49:00 -04005871 if (columns != nullptr)
5872 {
Geoff Langa953b522018-02-21 16:56:23 -05005873 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005874 }
5875
5876 if (rows != nullptr)
5877 {
Geoff Langa953b522018-02-21 16:56:23 -05005878 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005879 }
5880
5881 return true;
5882}
5883
5884template <typename ParamType>
5885bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005886 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005887 GLenum pname,
5888 GLsizei bufSize,
5889 const ParamType *params)
5890{
5891 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5892 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005893 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005894 return false;
5895 }
5896
5897 if (context->getTargetTexture(target) == nullptr)
5898 {
5899 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005900 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005901 return false;
5902 }
5903
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005904 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005905 if (bufSize >= 0 && bufSize < minBufSize)
5906 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005908 return false;
5909 }
5910
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005911 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5912 {
5913 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5914 return false;
5915 }
5916
Jamie Madillbe849e42017-05-02 15:49:00 -04005917 switch (pname)
5918 {
5919 case GL_TEXTURE_WRAP_R:
5920 case GL_TEXTURE_SWIZZLE_R:
5921 case GL_TEXTURE_SWIZZLE_G:
5922 case GL_TEXTURE_SWIZZLE_B:
5923 case GL_TEXTURE_SWIZZLE_A:
5924 case GL_TEXTURE_BASE_LEVEL:
5925 case GL_TEXTURE_MAX_LEVEL:
5926 case GL_TEXTURE_COMPARE_MODE:
5927 case GL_TEXTURE_COMPARE_FUNC:
5928 case GL_TEXTURE_MIN_LOD:
5929 case GL_TEXTURE_MAX_LOD:
5930 if (context->getClientMajorVersion() < 3)
5931 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005932 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005933 return false;
5934 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005935 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005937 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5938 "available without "
5939 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005940 return false;
5941 }
5942 break;
5943
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005944 case GL_GENERATE_MIPMAP:
5945 case GL_TEXTURE_CROP_RECT_OES:
5946 if (context->getClientMajorVersion() > 1)
5947 {
5948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5949 return false;
5950 }
5951 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005952 default:
5953 break;
5954 }
5955
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005956 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005957 {
5958 switch (pname)
5959 {
5960 case GL_TEXTURE_MIN_FILTER:
5961 case GL_TEXTURE_MAG_FILTER:
5962 case GL_TEXTURE_WRAP_S:
5963 case GL_TEXTURE_WRAP_T:
5964 case GL_TEXTURE_WRAP_R:
5965 case GL_TEXTURE_MIN_LOD:
5966 case GL_TEXTURE_MAX_LOD:
5967 case GL_TEXTURE_COMPARE_MODE:
5968 case GL_TEXTURE_COMPARE_FUNC:
5969 context->handleError(InvalidEnum()
5970 << "Invalid parameter for 2D multisampled textures.");
5971 return false;
5972 }
5973 }
5974
Jamie Madillbe849e42017-05-02 15:49:00 -04005975 switch (pname)
5976 {
5977 case GL_TEXTURE_WRAP_S:
5978 case GL_TEXTURE_WRAP_T:
5979 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005980 {
5981 bool restrictedWrapModes =
5982 target == TextureType::External || target == TextureType::Rectangle;
5983 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005984 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005985 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005986 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005987 }
5988 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005989
5990 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005991 {
5992 bool restrictedMinFilter =
5993 target == TextureType::External || target == TextureType::Rectangle;
5994 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005995 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005996 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005997 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005998 }
5999 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006000
6001 case GL_TEXTURE_MAG_FILTER:
6002 if (!ValidateTextureMagFilterValue(context, params))
6003 {
6004 return false;
6005 }
6006 break;
6007
6008 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04006009 if (!context->getExtensions().textureUsage)
6010 {
6011 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6012 return false;
6013 }
6014
Jamie Madillbe849e42017-05-02 15:49:00 -04006015 switch (ConvertToGLenum(params[0]))
6016 {
6017 case GL_NONE:
6018 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
6019 break;
6020
6021 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006023 return false;
6024 }
6025 break;
6026
6027 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07006028 {
6029 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6030 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04006031 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006032 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006033 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006034 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6035 }
6036 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006037
6038 case GL_TEXTURE_MIN_LOD:
6039 case GL_TEXTURE_MAX_LOD:
6040 // any value is permissible
6041 break;
6042
6043 case GL_TEXTURE_COMPARE_MODE:
6044 if (!ValidateTextureCompareModeValue(context, params))
6045 {
6046 return false;
6047 }
6048 break;
6049
6050 case GL_TEXTURE_COMPARE_FUNC:
6051 if (!ValidateTextureCompareFuncValue(context, params))
6052 {
6053 return false;
6054 }
6055 break;
6056
6057 case GL_TEXTURE_SWIZZLE_R:
6058 case GL_TEXTURE_SWIZZLE_G:
6059 case GL_TEXTURE_SWIZZLE_B:
6060 case GL_TEXTURE_SWIZZLE_A:
6061 switch (ConvertToGLenum(params[0]))
6062 {
6063 case GL_RED:
6064 case GL_GREEN:
6065 case GL_BLUE:
6066 case GL_ALPHA:
6067 case GL_ZERO:
6068 case GL_ONE:
6069 break;
6070
6071 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006072 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006073 return false;
6074 }
6075 break;
6076
6077 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006078 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006080 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006081 return false;
6082 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006083 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006085 context->handleError(InvalidOperation()
6086 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006087 return false;
6088 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006089 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006090 {
6091 context->handleError(InvalidOperation()
6092 << "Base level must be 0 for multisampled textures.");
6093 return false;
6094 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006095 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006096 {
6097 context->handleError(InvalidOperation()
6098 << "Base level must be 0 for rectangle textures.");
6099 return false;
6100 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006101 break;
6102
6103 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006104 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006105 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006106 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006107 return false;
6108 }
6109 break;
6110
6111 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6112 if (context->getClientVersion() < Version(3, 1))
6113 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006114 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006115 return false;
6116 }
6117 switch (ConvertToGLenum(params[0]))
6118 {
6119 case GL_DEPTH_COMPONENT:
6120 case GL_STENCIL_INDEX:
6121 break;
6122
6123 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006124 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006125 return false;
6126 }
6127 break;
6128
6129 case GL_TEXTURE_SRGB_DECODE_EXT:
6130 if (!ValidateTextureSRGBDecodeValue(context, params))
6131 {
6132 return false;
6133 }
6134 break;
6135
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006136 case GL_GENERATE_MIPMAP:
6137 case GL_TEXTURE_CROP_RECT_OES:
6138 if (context->getClientMajorVersion() > 1)
6139 {
6140 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6141 return false;
6142 }
6143 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006144 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006145 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006146 return false;
6147 }
6148
6149 return true;
6150}
6151
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006152template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6153template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006154
Jamie Madill5b772312018-03-08 20:28:32 -05006155bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006156{
6157 if (index >= MAX_VERTEX_ATTRIBS)
6158 {
6159 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6160 return false;
6161 }
6162
6163 return true;
6164}
6165
6166bool ValidateGetActiveUniformBlockivBase(Context *context,
6167 GLuint program,
6168 GLuint uniformBlockIndex,
6169 GLenum pname,
6170 GLsizei *length)
6171{
6172 if (length)
6173 {
6174 *length = 0;
6175 }
6176
6177 if (context->getClientMajorVersion() < 3)
6178 {
6179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6180 return false;
6181 }
6182
6183 Program *programObject = GetValidProgram(context, program);
6184 if (!programObject)
6185 {
6186 return false;
6187 }
6188
6189 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6190 {
6191 context->handleError(InvalidValue()
6192 << "uniformBlockIndex exceeds active uniform block count.");
6193 return false;
6194 }
6195
6196 switch (pname)
6197 {
6198 case GL_UNIFORM_BLOCK_BINDING:
6199 case GL_UNIFORM_BLOCK_DATA_SIZE:
6200 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6201 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6202 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6203 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6204 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6205 break;
6206
6207 default:
6208 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6209 return false;
6210 }
6211
6212 if (length)
6213 {
6214 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6215 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006216 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006217 programObject->getUniformBlockByIndex(uniformBlockIndex);
6218 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6219 }
6220 else
6221 {
6222 *length = 1;
6223 }
6224 }
6225
6226 return true;
6227}
6228
Jamie Madill9696d072017-08-26 23:19:57 -04006229template <typename ParamType>
6230bool ValidateSamplerParameterBase(Context *context,
6231 GLuint sampler,
6232 GLenum pname,
6233 GLsizei bufSize,
6234 ParamType *params)
6235{
6236 if (context->getClientMajorVersion() < 3)
6237 {
6238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6239 return false;
6240 }
6241
6242 if (!context->isSampler(sampler))
6243 {
6244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6245 return false;
6246 }
6247
6248 const GLsizei minBufSize = 1;
6249 if (bufSize >= 0 && bufSize < minBufSize)
6250 {
6251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6252 return false;
6253 }
6254
6255 switch (pname)
6256 {
6257 case GL_TEXTURE_WRAP_S:
6258 case GL_TEXTURE_WRAP_T:
6259 case GL_TEXTURE_WRAP_R:
6260 if (!ValidateTextureWrapModeValue(context, params, false))
6261 {
6262 return false;
6263 }
6264 break;
6265
6266 case GL_TEXTURE_MIN_FILTER:
6267 if (!ValidateTextureMinFilterValue(context, params, false))
6268 {
6269 return false;
6270 }
6271 break;
6272
6273 case GL_TEXTURE_MAG_FILTER:
6274 if (!ValidateTextureMagFilterValue(context, params))
6275 {
6276 return false;
6277 }
6278 break;
6279
6280 case GL_TEXTURE_MIN_LOD:
6281 case GL_TEXTURE_MAX_LOD:
6282 // any value is permissible
6283 break;
6284
6285 case GL_TEXTURE_COMPARE_MODE:
6286 if (!ValidateTextureCompareModeValue(context, params))
6287 {
6288 return false;
6289 }
6290 break;
6291
6292 case GL_TEXTURE_COMPARE_FUNC:
6293 if (!ValidateTextureCompareFuncValue(context, params))
6294 {
6295 return false;
6296 }
6297 break;
6298
6299 case GL_TEXTURE_SRGB_DECODE_EXT:
6300 if (!ValidateTextureSRGBDecodeValue(context, params))
6301 {
6302 return false;
6303 }
6304 break;
6305
Luc Ferron1b1a8642018-01-23 15:12:01 -05006306 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6307 {
6308 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6309 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6310 {
6311 return false;
6312 }
6313 }
6314 break;
6315
Jamie Madill9696d072017-08-26 23:19:57 -04006316 default:
6317 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6318 return false;
6319 }
6320
6321 return true;
6322}
6323
6324template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6325template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6326
6327bool ValidateGetSamplerParameterBase(Context *context,
6328 GLuint sampler,
6329 GLenum pname,
6330 GLsizei *length)
6331{
6332 if (length)
6333 {
6334 *length = 0;
6335 }
6336
6337 if (context->getClientMajorVersion() < 3)
6338 {
6339 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6340 return false;
6341 }
6342
6343 if (!context->isSampler(sampler))
6344 {
6345 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6346 return false;
6347 }
6348
6349 switch (pname)
6350 {
6351 case GL_TEXTURE_WRAP_S:
6352 case GL_TEXTURE_WRAP_T:
6353 case GL_TEXTURE_WRAP_R:
6354 case GL_TEXTURE_MIN_FILTER:
6355 case GL_TEXTURE_MAG_FILTER:
6356 case GL_TEXTURE_MIN_LOD:
6357 case GL_TEXTURE_MAX_LOD:
6358 case GL_TEXTURE_COMPARE_MODE:
6359 case GL_TEXTURE_COMPARE_FUNC:
6360 break;
6361
Luc Ferron1b1a8642018-01-23 15:12:01 -05006362 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6363 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6364 {
6365 return false;
6366 }
6367 break;
6368
Jamie Madill9696d072017-08-26 23:19:57 -04006369 case GL_TEXTURE_SRGB_DECODE_EXT:
6370 if (!context->getExtensions().textureSRGBDecode)
6371 {
6372 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6373 return false;
6374 }
6375 break;
6376
6377 default:
6378 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6379 return false;
6380 }
6381
6382 if (length)
6383 {
6384 *length = 1;
6385 }
6386 return true;
6387}
6388
6389bool ValidateGetInternalFormativBase(Context *context,
6390 GLenum target,
6391 GLenum internalformat,
6392 GLenum pname,
6393 GLsizei bufSize,
6394 GLsizei *numParams)
6395{
6396 if (numParams)
6397 {
6398 *numParams = 0;
6399 }
6400
6401 if (context->getClientMajorVersion() < 3)
6402 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006403 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006404 return false;
6405 }
6406
6407 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006408 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006409 {
6410 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6411 return false;
6412 }
6413
6414 switch (target)
6415 {
6416 case GL_RENDERBUFFER:
6417 break;
6418
6419 case GL_TEXTURE_2D_MULTISAMPLE:
6420 if (context->getClientVersion() < ES_3_1)
6421 {
6422 context->handleError(InvalidOperation()
6423 << "Texture target requires at least OpenGL ES 3.1.");
6424 return false;
6425 }
6426 break;
6427
6428 default:
6429 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6430 return false;
6431 }
6432
6433 if (bufSize < 0)
6434 {
6435 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6436 return false;
6437 }
6438
6439 GLsizei maxWriteParams = 0;
6440 switch (pname)
6441 {
6442 case GL_NUM_SAMPLE_COUNTS:
6443 maxWriteParams = 1;
6444 break;
6445
6446 case GL_SAMPLES:
6447 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6448 break;
6449
6450 default:
6451 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6452 return false;
6453 }
6454
6455 if (numParams)
6456 {
6457 // glGetInternalFormativ will not overflow bufSize
6458 *numParams = std::min(bufSize, maxWriteParams);
6459 }
6460
6461 return true;
6462}
6463
Jamie Madille98b1b52018-03-08 09:47:23 -05006464bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6465{
Jamie Madill427064d2018-04-13 16:20:34 -04006466 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006467 {
6468 context->handleError(InvalidOperation());
6469 return false;
6470 }
6471 return true;
6472}
6473
Lingfeng Yang038dd532018-03-29 17:31:52 -07006474bool ValidateMultitextureUnit(Context *context, GLenum texture)
6475{
6476 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6477 {
6478 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6479 return false;
6480 }
6481 return true;
6482}
6483
Jamie Madillc29968b2016-01-20 11:17:23 -05006484} // namespace gl