blob: 5bd5ad77a3bc934383165017bcc7ebf320a87e22 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040025#include "libANGLE/validationES2.h"
26#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28#include "common/mathutil.h"
29#include "common/utilities.h"
30
Jamie Madille2e406c2016-06-02 13:04:10 -040031using namespace angle;
32
Geoff Lange8ebe7f2013-08-05 15:03:13 -040033namespace gl
34{
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050037bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
38{
39 // List of compressed format that require that the texture size is smaller than or a multiple of
40 // the compressed block size.
41 switch (internalFormat)
42 {
43 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
44 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
46 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
47 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
51 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
52 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
53 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
57 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 return true;
jchen10a99ed552017-09-22 08:10:32 +080059
Luc Ferron9dbaeba2018-02-01 07:26:59 -050060 default:
61 return false;
62 }
63}
64bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
65{
66 // Compressed sub textures have additional formats that requires exact size.
67 // ES 3.1, Section 8.7, Page 171
68 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
69 IsETC2EACFormat(internalFormat);
70}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030071
72bool DifferenceCanOverflow(GLint a, GLint b)
73{
74 CheckedNumeric<GLint> checkedA(a);
75 checkedA -= b;
76 // Use negation to make sure that the difference can't overflow regardless of the order.
77 checkedA = -checkedA;
78 return !checkedA.IsValid();
79}
80
Jamie Madill5b772312018-03-08 20:28:32 -050081bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040082{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070083 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040084 const gl::Program *program = state.getProgram();
85
Corentin Wallez327411e2016-12-09 11:09:17 -050086 bool webglCompatibility = context->getExtensions().webglCompatibility;
87
Jamie Madill51af38b2018-04-15 08:50:56 -040088 const VertexArray *vao = state.getVertexArray();
89 const AttributesMask &clientAttribs = vao->getEnabledClientMemoryAttribsMask();
90
91 if (clientAttribs.any())
92 {
93 if (webglCompatibility || !state.areClientArraysEnabled())
94 {
95 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
96 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
97 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
98 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
99 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
100 return false;
101 }
102 else if (vao->hasEnabledNullPointerClientArray())
103 {
104 // This is an application error that would normally result in a crash, but we catch it
105 // and return an error
106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
107 return false;
108 }
109 }
110
111 // If we're drawing zero vertices, we have enough data.
112 if (vertexCount <= 0 || primcount <= 0)
113 {
114 return true;
115 }
116
Jamie Madill231c7f52017-04-26 13:45:37 -0400117 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800118 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill51af38b2018-04-15 08:50:56 -0400119
Jamie Madill02c9c042018-04-17 13:43:48 -0400120 const AttributesMask &activeAttribs = (program->getActiveAttribLocationsMask() &
121 vao->getEnabledAttributesMask() & ~clientAttribs);
Jamie Madill51af38b2018-04-15 08:50:56 -0400122
123 for (size_t attributeIndex : activeAttribs)
Jamie Madill1ca74672015-07-21 15:14:11 -0400124 {
125 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400126 ASSERT(attrib.enabled);
Corentin Wallez672f7f32017-06-15 17:42:17 -0400127
Lingfeng Yang038dd532018-03-29 17:31:52 -0700128 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400129 ASSERT(program->isAttribLocationActive(attributeIndex));
Corentin Wallezfd456442016-12-21 17:57:00 -0500130
Jamie Madill02c9c042018-04-17 13:43:48 -0400131 GLint maxVertexElement = maxVertex;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300132 GLuint divisor = binding.getDivisor();
Jamie Madill02c9c042018-04-17 13:43:48 -0400133 if (divisor != 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300135 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 }
137
138 // We do manual overflow checks here instead of using safe_math.h because it was
139 // a bottleneck. Thanks to some properties of GL we know inequalities that can
140 // help us make the overflow checks faster.
141
142 // The max possible attribSize is 16 for a vector of 4 32 bit values.
143 constexpr uint64_t kMaxAttribSize = 16;
144 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
145 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
146
147 // We know attribStride is given as a GLsizei which is typedefed to int.
148 // We also know an upper bound for attribSize.
Jamie Madill02c9c042018-04-17 13:43:48 -0400149 static_assert(std::is_same<int, GLsizei>::value, "Unexpected type");
150 ASSERT(ComputeVertexAttributeStride(attrib, binding) == binding.getStride());
151 uint64_t attribStride = binding.getStride();
152 ASSERT(attribStride <= kIntMax && ComputeVertexAttributeTypeSize(attrib) <= kMaxAttribSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500153
Jamie Madill02c9c042018-04-17 13:43:48 -0400154 // Computing the product of two 32-bit ints will fit in 64 bits without overflow.
155 static_assert(kIntMax * kIntMax < kUint64Max, "Unexpected overflow");
156 uint64_t attribDataSizeMinusAttribSize = maxVertexElement * attribStride;
Corentin Wallezfd456442016-12-21 17:57:00 -0500157
158 // An overflow can happen when adding the offset, check for it.
Jamie Madill02c9c042018-04-17 13:43:48 -0400159 if (attribDataSizeMinusAttribSize > kUint64Max - attrib.cachedSizePlusRelativeOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500160 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500162 return false;
163 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500164
165 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
Jamie Madill02c9c042018-04-17 13:43:48 -0400166 // We can return INVALID_OPERATION if our array buffer does not have enough backing data.
167 if (attribDataSizeMinusAttribSize + attrib.cachedSizePlusRelativeOffset >
168 binding.getCachedBufferSizeMinusOffset())
Corentin Wallezfd456442016-12-21 17:57:00 -0500169 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500171 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400172 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400173 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800174
Jamie Madill02c9c042018-04-17 13:43:48 -0400175 // TODO(jmadill): Cache this. http://anglebug.com/1391
176 if (webglCompatibility)
177 {
178 for (size_t attributeIndex : activeAttribs)
James Darpiniane8a93c62018-01-04 18:02:24 -0800179 {
Jamie Madill02c9c042018-04-17 13:43:48 -0400180 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
181 ASSERT(attrib.enabled);
182
183 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
184
185 gl::Buffer *buffer = binding.getBuffer().get();
Jamie Madill629bb252018-04-20 11:01:33 -0400186 if (buffer && buffer->isBoundForTransformFeedbackAndOtherUse())
Jamie Madill02c9c042018-04-17 13:43:48 -0400187 {
188 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
189 VertexBufferBoundForTransformFeedback);
190 return false;
191 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800192 }
Jamie Madill1ca74672015-07-21 15:14:11 -0400193 }
194
195 return true;
196}
197
Jamie Madill5b772312018-03-08 20:28:32 -0500198bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400199{
200 switch (type)
201 {
202 // Types referenced in Table 3.4 of the ES 2.0.25 spec
203 case GL_UNSIGNED_BYTE:
204 case GL_UNSIGNED_SHORT_4_4_4_4:
205 case GL_UNSIGNED_SHORT_5_5_5_1:
206 case GL_UNSIGNED_SHORT_5_6_5:
207 return context->getClientVersion() >= ES_2_0;
208
209 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
210 case GL_BYTE:
211 case GL_INT:
212 case GL_SHORT:
213 case GL_UNSIGNED_INT:
214 case GL_UNSIGNED_INT_10F_11F_11F_REV:
215 case GL_UNSIGNED_INT_24_8:
216 case GL_UNSIGNED_INT_2_10_10_10_REV:
217 case GL_UNSIGNED_INT_5_9_9_9_REV:
218 case GL_UNSIGNED_SHORT:
219 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
220 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
221 return context->getClientVersion() >= ES_3_0;
222
223 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400224 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
225 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400226
227 case GL_HALF_FLOAT:
228 return context->getClientVersion() >= ES_3_0 ||
229 context->getExtensions().textureHalfFloat;
230
231 case GL_HALF_FLOAT_OES:
232 return context->getExtensions().colorBufferHalfFloat;
233
234 default:
235 return false;
236 }
237}
238
Jamie Madill5b772312018-03-08 20:28:32 -0500239bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400240{
241 switch (format)
242 {
243 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
244 case GL_RGBA:
245 case GL_RGB:
246 case GL_ALPHA:
247 return context->getClientVersion() >= ES_2_0;
248
249 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
250 case GL_RG:
251 case GL_RED:
252 case GL_RGBA_INTEGER:
253 case GL_RGB_INTEGER:
254 case GL_RG_INTEGER:
255 case GL_RED_INTEGER:
256 return context->getClientVersion() >= ES_3_0;
257
258 case GL_SRGB_ALPHA_EXT:
259 case GL_SRGB_EXT:
260 return context->getExtensions().sRGB;
261
262 case GL_BGRA_EXT:
263 return context->getExtensions().readFormatBGRA;
264
265 default:
266 return false;
267 }
268}
269
Jamie Madill5b772312018-03-08 20:28:32 -0500270bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400271 GLenum framebufferComponentType,
272 GLenum format,
273 GLenum type)
274{
275 switch (framebufferComponentType)
276 {
277 case GL_UNSIGNED_NORMALIZED:
278 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
279 // ReadPixels with BGRA even if the extension is not present
280 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
281 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
282 type == GL_UNSIGNED_BYTE);
283
284 case GL_SIGNED_NORMALIZED:
285 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
286
287 case GL_INT:
288 return (format == GL_RGBA_INTEGER && type == GL_INT);
289
290 case GL_UNSIGNED_INT:
291 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
292
293 case GL_FLOAT:
294 return (format == GL_RGBA && type == GL_FLOAT);
295
296 default:
297 UNREACHABLE();
298 return false;
299 }
300}
301
Geoff Langc1984ed2016-10-07 12:41:00 -0400302template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400303bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400304{
305 switch (ConvertToGLenum(params[0]))
306 {
307 case GL_CLAMP_TO_EDGE:
308 break;
309
310 case GL_REPEAT:
311 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400312 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400313 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400314 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700315 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400316 return false;
317 }
318 break;
319
320 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400322 return false;
323 }
324
325 return true;
326}
327
328template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400329bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400330{
331 switch (ConvertToGLenum(params[0]))
332 {
333 case GL_NEAREST:
334 case GL_LINEAR:
335 break;
336
337 case GL_NEAREST_MIPMAP_NEAREST:
338 case GL_LINEAR_MIPMAP_NEAREST:
339 case GL_NEAREST_MIPMAP_LINEAR:
340 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400341 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400342 {
343 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700344 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400345 return false;
346 }
347 break;
348
349 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700350 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400351 return false;
352 }
353
354 return true;
355}
356
357template <typename ParamType>
358bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
359{
360 switch (ConvertToGLenum(params[0]))
361 {
362 case GL_NEAREST:
363 case GL_LINEAR:
364 break;
365
366 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700367 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400368 return false;
369 }
370
371 return true;
372}
373
374template <typename ParamType>
375bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
376{
377 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
378 switch (ConvertToGLenum(params[0]))
379 {
380 case GL_NONE:
381 case GL_COMPARE_REF_TO_TEXTURE:
382 break;
383
384 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400386 return false;
387 }
388
389 return true;
390}
391
392template <typename ParamType>
393bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
394{
395 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
396 switch (ConvertToGLenum(params[0]))
397 {
398 case GL_LEQUAL:
399 case GL_GEQUAL:
400 case GL_LESS:
401 case GL_GREATER:
402 case GL_EQUAL:
403 case GL_NOTEQUAL:
404 case GL_ALWAYS:
405 case GL_NEVER:
406 break;
407
408 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700409 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400410 return false;
411 }
412
413 return true;
414}
415
416template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700417bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
418{
419 if (!context->getExtensions().textureSRGBDecode)
420 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700422 return false;
423 }
424
425 switch (ConvertToGLenum(params[0]))
426 {
427 case GL_DECODE_EXT:
428 case GL_SKIP_DECODE_EXT:
429 break;
430
431 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700433 return false;
434 }
435
436 return true;
437}
438
Luc Ferron1b1a8642018-01-23 15:12:01 -0500439bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
440{
441 if (!context->getExtensions().textureFilterAnisotropic)
442 {
443 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
444 return false;
445 }
446
447 return true;
448}
449
450bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
451{
452 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
453 {
454 return false;
455 }
456
457 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
458
459 if (paramValue < 1 || paramValue > largest)
460 {
461 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
462 return false;
463 }
464
465 return true;
466}
467
Jamie Madill5b772312018-03-08 20:28:32 -0500468bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400469{
470 const Program *program = context->getGLState().getProgram();
471 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
472
Brandon Jonesc405ae72017-12-06 14:15:03 -0800473 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
474 framebuffer->getDrawBufferTypeMask().to_ulong(),
475 program->getActiveOutputVariables().to_ulong(),
476 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400477 {
Brandon Jones76746f92017-11-22 11:44:41 -0800478 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
479 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400480 }
481
482 return true;
483}
484
Jamie Madill5b772312018-03-08 20:28:32 -0500485bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400486{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700487 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400488 const Program *program = context->getGLState().getProgram();
489 const VertexArray *vao = context->getGLState().getVertexArray();
490
Brandon Jonesc405ae72017-12-06 14:15:03 -0800491 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
492 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
493 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
494
495 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
496 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
497 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
498
499 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
500 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400501 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800502 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
503 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400504 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400505 return true;
506}
507
Jiawei Shaofccebff2018-03-08 13:51:02 +0800508bool IsCompatibleDrawModeWithGeometryShader(GLenum drawMode,
509 GLenum geometryShaderInputPrimitiveType)
510{
511 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
512 switch (geometryShaderInputPrimitiveType)
513 {
514 case GL_POINTS:
515 return drawMode == GL_POINTS;
516 case GL_LINES:
517 return drawMode == GL_LINES || drawMode == GL_LINE_STRIP || drawMode == GL_LINE_LOOP;
518 case GL_LINES_ADJACENCY_EXT:
519 return drawMode == GL_LINES_ADJACENCY_EXT || drawMode == GL_LINE_STRIP_ADJACENCY_EXT;
520 case GL_TRIANGLES:
521 return drawMode == GL_TRIANGLES || drawMode == GL_TRIANGLE_FAN ||
522 drawMode == GL_TRIANGLE_STRIP;
523 case GL_TRIANGLES_ADJACENCY_EXT:
524 return drawMode == GL_TRIANGLES_ADJACENCY_EXT ||
525 drawMode == GL_TRIANGLE_STRIP_ADJACENCY_EXT;
526 default:
527 UNREACHABLE();
528 return false;
529 }
530}
531
Geoff Langf41a7152016-09-19 15:11:17 -0400532} // anonymous namespace
533
Brandon Jonesd1049182018-03-28 10:02:20 -0700534void SetRobustLengthParam(GLsizei *length, GLsizei value)
535{
536 if (length)
537 {
538 *length = value;
539 }
540}
541
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500542bool IsETC2EACFormat(const GLenum format)
543{
544 // ES 3.1, Table 8.19
545 switch (format)
546 {
547 case GL_COMPRESSED_R11_EAC:
548 case GL_COMPRESSED_SIGNED_R11_EAC:
549 case GL_COMPRESSED_RG11_EAC:
550 case GL_COMPRESSED_SIGNED_RG11_EAC:
551 case GL_COMPRESSED_RGB8_ETC2:
552 case GL_COMPRESSED_SRGB8_ETC2:
553 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
554 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
555 case GL_COMPRESSED_RGBA8_ETC2_EAC:
556 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
557 return true;
558
559 default:
560 return false;
561 }
562}
563
Jamie Madill5b772312018-03-08 20:28:32 -0500564bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400565{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800566 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400567 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800568 case TextureType::_2D:
569 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800570 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400571
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800572 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400573 return context->getExtensions().textureRectangle;
574
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800575 case TextureType::_3D:
576 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800577 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500578
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800579 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800580 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400581
He Yunchaoced53ae2016-11-29 15:00:51 +0800582 default:
583 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500584 }
Jamie Madill35d15012013-10-07 10:46:37 -0400585}
586
Jamie Madill5b772312018-03-08 20:28:32 -0500587bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500588{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800589 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500590 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800591 case TextureType::_2D:
592 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500593 return true;
594
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800595 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400596 return context->getExtensions().textureRectangle;
597
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500598 default:
599 return false;
600 }
601}
602
Jamie Madill5b772312018-03-08 20:28:32 -0500603bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500604{
605 switch (target)
606 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800607 case TextureType::_3D:
608 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300609 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500610
611 default:
612 return false;
613 }
614}
615
Ian Ewellbda75592016-04-18 17:25:54 -0400616// Most texture GL calls are not compatible with external textures, so we have a separate validation
617// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500618bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400619{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800620 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400621 (context->getExtensions().eglImageExternal ||
622 context->getExtensions().eglStreamConsumerExternal);
623}
624
Shannon Woods4dfed832014-03-17 20:03:39 -0400625// This function differs from ValidTextureTarget in that the target must be
626// usable as the destination of a 2D operation-- so a cube face is valid, but
627// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400628// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500629bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400630{
631 switch (target)
632 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800633 case TextureTarget::_2D:
634 case TextureTarget::CubeMapNegativeX:
635 case TextureTarget::CubeMapNegativeY:
636 case TextureTarget::CubeMapNegativeZ:
637 case TextureTarget::CubeMapPositiveX:
638 case TextureTarget::CubeMapPositiveY:
639 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800640 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800641 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400642 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800643 default:
644 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500645 }
646}
647
Jamie Madill5b772312018-03-08 20:28:32 -0500648bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -0400649 GLenum mode,
650 GLsizei count,
651 GLenum type,
652 const GLvoid *indices,
653 GLsizei primcount)
654{
655 if (primcount < 0)
656 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700657 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400658 return false;
659 }
660
661 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
662 {
663 return false;
664 }
665
Jamie Madill9fdaa492018-02-16 10:52:11 -0500666 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400667}
668
669bool ValidateDrawArraysInstancedBase(Context *context,
670 GLenum mode,
671 GLint first,
672 GLsizei count,
673 GLsizei primcount)
674{
675 if (primcount < 0)
676 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700677 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400678 return false;
679 }
680
681 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
682 {
683 return false;
684 }
685
Jamie Madill9fdaa492018-02-16 10:52:11 -0500686 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400687}
688
Jamie Madill5b772312018-03-08 20:28:32 -0500689bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400690{
691 // Verify there is at least one active attribute with a divisor of zero
692 const State &state = context->getGLState();
693
694 Program *program = state.getProgram();
695
696 const auto &attribs = state.getVertexArray()->getVertexAttributes();
697 const auto &bindings = state.getVertexArray()->getVertexBindings();
698 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
699 {
700 const VertexAttribute &attrib = attribs[attributeIndex];
701 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300702 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400703 {
704 return true;
705 }
706 }
707
Brandon Jonesafa75152017-07-21 13:11:29 -0700708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400709 return false;
710}
711
Jamie Madill5b772312018-03-08 20:28:32 -0500712bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500713{
714 switch (target)
715 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800716 case TextureType::_3D:
717 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800718 return true;
719 default:
720 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400721 }
722}
723
Jamie Madill5b772312018-03-08 20:28:32 -0500724bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800725{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800726 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800727 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800728 case TextureType::_2D:
729 case TextureType::_2DArray:
730 case TextureType::_2DMultisample:
731 case TextureType::CubeMap:
732 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800733 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800734 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400735 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800736 default:
737 return false;
738 }
739}
740
Jamie Madill5b772312018-03-08 20:28:32 -0500741bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500742{
He Yunchaoced53ae2016-11-29 15:00:51 +0800743 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
744 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400745 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500746
747 switch (target)
748 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800749 case GL_FRAMEBUFFER:
750 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400751
He Yunchaoced53ae2016-11-29 15:00:51 +0800752 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800753 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400754 return (context->getExtensions().framebufferBlit ||
755 context->getClientMajorVersion() >= 3);
756
He Yunchaoced53ae2016-11-29 15:00:51 +0800757 default:
758 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500759 }
760}
761
Jamie Madill5b772312018-03-08 20:28:32 -0500762bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400763{
Jamie Madillc29968b2016-01-20 11:17:23 -0500764 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400765 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800766 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400767 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800768 case TextureType::_2D:
769 case TextureType::_2DArray:
770 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500771 maxDimension = caps.max2DTextureSize;
772 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800773 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800774 maxDimension = caps.maxCubeMapTextureSize;
775 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800776 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400777 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800778 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800779 maxDimension = caps.max3DTextureSize;
780 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800781 default:
782 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400783 }
784
Brandon Jones6cad5662017-06-14 13:25:13 -0700785 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400786}
787
Jamie Madill5b772312018-03-08 20:28:32 -0500788bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800789 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700790 GLint level,
791 GLsizei width,
792 GLsizei height,
793 GLsizei depth,
794 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400795{
Brandon Jones6cad5662017-06-14 13:25:13 -0700796 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400797 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700798 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400799 return false;
800 }
Austin Kinross08528e12015-10-07 16:24:40 -0700801 // TexSubImage parameters can be NPOT without textureNPOT extension,
802 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500803 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500804 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500805 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400806 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400807 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700808 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400809 return false;
810 }
811
812 if (!ValidMipLevel(context, target, level))
813 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700814 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400815 return false;
816 }
817
818 return true;
819}
820
Geoff Lang966c9402017-04-18 12:38:27 -0400821bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
822{
823 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
824 (size % blockSize == 0);
825}
826
Jamie Madill5b772312018-03-08 20:28:32 -0500827bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500828 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400829 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500830 GLsizei width,
831 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400832{
Geoff Langca271392017-04-05 12:30:00 -0400833 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400834 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400835 {
836 return false;
837 }
838
Geoff Lang966c9402017-04-18 12:38:27 -0400839 if (width < 0 || height < 0)
840 {
841 return false;
842 }
843
844 if (CompressedTextureFormatRequiresExactSize(internalFormat))
845 {
846 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
847 // block size for level 0 but WebGL disallows this.
848 bool smallerThanBlockSizeAllowed =
849 level > 0 || !context->getExtensions().webglCompatibility;
850
851 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
852 smallerThanBlockSizeAllowed) ||
853 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
854 smallerThanBlockSizeAllowed))
855 {
856 return false;
857 }
858 }
859
860 return true;
861}
862
Jamie Madill5b772312018-03-08 20:28:32 -0500863bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400864 GLenum internalFormat,
865 GLint xoffset,
866 GLint yoffset,
867 GLsizei width,
868 GLsizei height,
869 size_t textureWidth,
870 size_t textureHeight)
871{
872 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
873 if (!formatInfo.compressed)
874 {
875 return false;
876 }
877
Geoff Lang44ff5a72017-02-03 15:15:43 -0500878 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400879 {
880 return false;
881 }
882
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500883 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400884 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500885 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400886 yoffset % formatInfo.compressedBlockHeight != 0)
887 {
888 return false;
889 }
890
891 // Allowed to either have data that is a multiple of block size or is smaller than the block
892 // size but fills the entire mip
893 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
894 static_cast<size_t>(width) == textureWidth &&
895 static_cast<size_t>(height) == textureHeight;
896 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
897 (height % formatInfo.compressedBlockHeight) == 0;
898 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400899 {
900 return false;
901 }
902 }
903
Geoff Langd4f180b2013-09-24 13:57:44 -0400904 return true;
905}
906
Jamie Madill5b772312018-03-08 20:28:32 -0500907bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800908 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400909 GLsizei width,
910 GLsizei height,
911 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400912 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400913 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400914 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400915 GLsizei imageSize)
916{
Corentin Wallez336129f2017-10-17 15:55:40 -0400917 gl::Buffer *pixelUnpackBuffer =
918 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400919 if (pixelUnpackBuffer == nullptr && imageSize < 0)
920 {
921 // Checks are not required
922 return true;
923 }
924
925 // ...the data would be unpacked from the buffer object such that the memory reads required
926 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400927 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
928 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400929 const gl::Extents size(width, height, depth);
930 const auto &unpack = context->getGLState().getUnpackState();
931
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800932 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400933 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
934 if (endByteOrErr.isError())
935 {
936 context->handleError(endByteOrErr.getError());
937 return false;
938 }
939
940 GLuint endByte = endByteOrErr.getResult();
941
942 if (pixelUnpackBuffer)
943 {
944 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
945 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
946 checkedEndByte += checkedOffset;
947
948 if (!checkedEndByte.IsValid() ||
949 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
950 {
951 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500952 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400953 return false;
954 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800955 if (context->getExtensions().webglCompatibility &&
956 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
957 {
958 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
959 PixelUnpackBufferBoundForTransformFeedback);
960 return false;
961 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400962 }
963 else
964 {
965 ASSERT(imageSize >= 0);
966 if (pixels == nullptr && imageSize != 0)
967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500968 context->handleError(InvalidOperation()
969 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400970 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400971 }
972
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400973 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500975 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400976 return false;
977 }
978 }
979
980 return true;
981}
982
Geoff Lang37dde692014-01-31 16:34:54 -0500983bool ValidQueryType(const Context *context, GLenum queryType)
984{
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
986 "GL extension enums not equal.");
987 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
988 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500989
990 switch (queryType)
991 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800992 case GL_ANY_SAMPLES_PASSED:
993 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400994 return context->getClientMajorVersion() >= 3 ||
995 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800996 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
997 return (context->getClientMajorVersion() >= 3);
998 case GL_TIME_ELAPSED_EXT:
999 return context->getExtensions().disjointTimerQuery;
1000 case GL_COMMANDS_COMPLETED_CHROMIUM:
1001 return context->getExtensions().syncQuery;
Jiawei Shaod2fa07e2018-03-15 09:20:25 +08001002 case GL_PRIMITIVES_GENERATED_EXT:
1003 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +08001004 default:
1005 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001006 }
1007}
1008
Jamie Madill5b772312018-03-08 20:28:32 -05001009bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001010 GLenum type,
1011 GLboolean normalized,
1012 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001013 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001014 bool pureInteger)
1015{
1016 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001017 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1018 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1019 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1020 // parameter exceeds 255.
1021 constexpr GLsizei kMaxWebGLStride = 255;
1022 if (stride > kMaxWebGLStride)
1023 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001024 context->handleError(InvalidValue()
1025 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001026 return false;
1027 }
1028
1029 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1030 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1031 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1032 // or an INVALID_OPERATION error is generated.
1033 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1034 size_t typeSize = GetVertexFormatTypeSize(internalType);
1035
1036 ASSERT(isPow2(typeSize) && typeSize > 0);
1037 size_t sizeMask = (typeSize - 1);
1038 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1039 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001040 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001041 return false;
1042 }
1043
1044 if ((stride & sizeMask) != 0)
1045 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001046 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001047 return false;
1048 }
1049
1050 return true;
1051}
1052
Jamie Madill5b772312018-03-08 20:28:32 -05001053Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001054{
He Yunchaoced53ae2016-11-29 15:00:51 +08001055 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1056 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1057 // or program object and INVALID_OPERATION if the provided name identifies an object
1058 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001059
Dian Xiang769769a2015-09-09 15:20:08 -07001060 Program *validProgram = context->getProgram(id);
1061
1062 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001063 {
Dian Xiang769769a2015-09-09 15:20:08 -07001064 if (context->getShader(id))
1065 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001067 }
1068 else
1069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001070 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001071 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001072 }
Dian Xiang769769a2015-09-09 15:20:08 -07001073
1074 return validProgram;
1075}
1076
Jamie Madill5b772312018-03-08 20:28:32 -05001077Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001078{
1079 // See ValidProgram for spec details.
1080
1081 Shader *validShader = context->getShader(id);
1082
1083 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001084 {
Dian Xiang769769a2015-09-09 15:20:08 -07001085 if (context->getProgram(id))
1086 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001087 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001088 }
1089 else
1090 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001091 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001092 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001093 }
Dian Xiang769769a2015-09-09 15:20:08 -07001094
1095 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001096}
1097
Geoff Langb1196682014-07-23 13:47:29 -04001098bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001099{
Geoff Langfa125c92017-10-24 13:01:46 -04001100 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001101 {
Geoff Langfa125c92017-10-24 13:01:46 -04001102 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1103 {
1104 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1105 return false;
1106 }
Jamie Madillb4472272014-07-03 10:38:55 -04001107
Geoff Langfa125c92017-10-24 13:01:46 -04001108 // Color attachment 0 is validated below because it is always valid
1109 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001110 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001111 {
Geoff Langfa125c92017-10-24 13:01:46 -04001112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001113 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001114 }
1115 }
1116 else
1117 {
1118 switch (attachment)
1119 {
Geoff Langfa125c92017-10-24 13:01:46 -04001120 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001121 case GL_DEPTH_ATTACHMENT:
1122 case GL_STENCIL_ATTACHMENT:
1123 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001124
He Yunchaoced53ae2016-11-29 15:00:51 +08001125 case GL_DEPTH_STENCIL_ATTACHMENT:
1126 if (!context->getExtensions().webglCompatibility &&
1127 context->getClientMajorVersion() < 3)
1128 {
Geoff Langfa125c92017-10-24 13:01:46 -04001129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001130 return false;
1131 }
1132 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001133
He Yunchaoced53ae2016-11-29 15:00:51 +08001134 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001135 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001136 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001137 }
1138 }
1139
1140 return true;
1141}
1142
Jamie Madill5b772312018-03-08 20:28:32 -05001143bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001144 GLenum target,
1145 GLsizei samples,
1146 GLenum internalformat,
1147 GLsizei width,
1148 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001149{
1150 switch (target)
1151 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001152 case GL_RENDERBUFFER:
1153 break;
1154 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158
1159 if (width < 0 || height < 0 || samples < 0)
1160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001161 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001162 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001163 }
1164
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001165 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1166 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1167
1168 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001169 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
1175 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1176 // 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 -08001177 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001178 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1179 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001180 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001181 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001182 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001183 }
1184
Geoff Langaae65a42014-05-26 12:43:44 -04001185 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001187 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001189 }
1190
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001191 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001192 if (handle == 0)
1193 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001194 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001195 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001196 }
1197
1198 return true;
1199}
1200
He Yunchaoced53ae2016-11-29 15:00:51 +08001201bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1202 GLenum target,
1203 GLenum attachment,
1204 GLenum renderbuffertarget,
1205 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001206{
Geoff Lange8afa902017-09-27 15:00:43 -04001207 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001209 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001210 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001211 }
1212
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001213 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001214
Jamie Madill84115c92015-04-23 15:00:07 -04001215 ASSERT(framebuffer);
1216 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001219 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001220 }
1221
Jamie Madillb4472272014-07-03 10:38:55 -04001222 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001223 {
Jamie Madillb4472272014-07-03 10:38:55 -04001224 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001225 }
1226
Jamie Madillab9d82c2014-01-21 16:38:14 -05001227 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1228 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1229 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1230 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1231 if (renderbuffer != 0)
1232 {
1233 if (!context->getRenderbuffer(renderbuffer))
1234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001236 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001237 }
1238 }
1239
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001240 return true;
1241}
1242
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001243bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001244 GLint srcX0,
1245 GLint srcY0,
1246 GLint srcX1,
1247 GLint srcY1,
1248 GLint dstX0,
1249 GLint dstY0,
1250 GLint dstX1,
1251 GLint dstY1,
1252 GLbitfield mask,
1253 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254{
1255 switch (filter)
1256 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001257 case GL_NEAREST:
1258 break;
1259 case GL_LINEAR:
1260 break;
1261 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001262 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001263 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001264 }
1265
1266 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001268 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001269 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 }
1271
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001272 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1273 // color buffer, leaving only nearest being unfiltered from above
1274 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001276 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001277 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 }
1279
Jamie Madill51f40ec2016-06-15 14:06:00 -04001280 const auto &glState = context->getGLState();
1281 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1282 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001283
1284 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001285 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001286 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001287 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001288 }
1289
Jamie Madill427064d2018-04-13 16:20:34 -04001290 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001291 {
Jamie Madill48faf802014-11-06 15:27:22 -05001292 return false;
1293 }
1294
Jamie Madill427064d2018-04-13 16:20:34 -04001295 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001296 {
Jamie Madill48faf802014-11-06 15:27:22 -05001297 return false;
1298 }
1299
Qin Jiajiaaef92162018-02-27 13:51:44 +08001300 if (readFramebuffer->id() == drawFramebuffer->id())
1301 {
1302 context->handleError(InvalidOperation());
1303 return false;
1304 }
1305
Jamie Madille98b1b52018-03-08 09:47:23 -05001306 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001307 {
Geoff Langb1196682014-07-23 13:47:29 -04001308 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001309 }
1310
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001311 if (context->getExtensions().webglCompatibility)
1312 {
1313 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1314 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
1315 {
1316 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1317 return false;
1318 }
1319 }
1320
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001321 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1322
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 if (mask & GL_COLOR_BUFFER_BIT)
1324 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001325 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001326 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327
He Yunchao66a41a22016-12-15 16:45:05 +08001328 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001330 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331
Geoff Langa15472a2015-08-11 11:48:03 -04001332 for (size_t drawbufferIdx = 0;
1333 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 {
Geoff Langa15472a2015-08-11 11:48:03 -04001335 const FramebufferAttachment *attachment =
1336 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1337 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001338 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001339 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001340
Geoff Langb2f3d052013-08-13 12:49:27 -04001341 // The GL ES 3.0.2 spec (pg 193) states that:
1342 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001343 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1344 // as well
1345 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1346 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001347 // Changes with EXT_color_buffer_float:
1348 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001349 GLenum readComponentType = readFormat.info->componentType;
1350 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001351 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001352 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001353 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001354 drawComponentType == GL_SIGNED_NORMALIZED);
1355
1356 if (extensions.colorBufferFloat)
1357 {
1358 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1359 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1360
1361 if (readFixedOrFloat != drawFixedOrFloat)
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidOperation()
1364 << "If the read buffer contains fixed-point or "
1365 "floating-point values, the draw buffer must "
1366 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001367 return false;
1368 }
1369 }
1370 else if (readFixedPoint != drawFixedPoint)
1371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001372 context->handleError(InvalidOperation()
1373 << "If the read buffer contains fixed-point values, "
1374 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001375 return false;
1376 }
1377
1378 if (readComponentType == GL_UNSIGNED_INT &&
1379 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001381 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001382 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001383 }
1384
Jamie Madill6163c752015-12-07 16:32:59 -05001385 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001388 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
1390
Jamie Madilla3944d42016-07-22 22:13:26 -04001391 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001392 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001394 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001395 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 }
Geoff Lange4915782017-04-12 15:19:07 -04001397
1398 if (context->getExtensions().webglCompatibility &&
1399 *readColorBuffer == *attachment)
1400 {
1401 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001402 InvalidOperation()
1403 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001404 return false;
1405 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406 }
1407 }
1408
Jamie Madilla3944d42016-07-22 22:13:26 -04001409 if ((readFormat.info->componentType == GL_INT ||
1410 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1411 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001413 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001414 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001415 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 }
He Yunchao66a41a22016-12-15 16:45:05 +08001417 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1418 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1419 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1420 // situation is an application error that would lead to a crash in ANGLE.
1421 else if (drawFramebuffer->hasEnabledDrawBuffer())
1422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(
1424 InvalidOperation()
1425 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001426 return false;
1427 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428 }
1429
He Yunchaoced53ae2016-11-29 15:00:51 +08001430 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001431 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1432 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001434 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001436 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001437 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001438 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001439 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001440
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001441 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001442 {
Kenneth Russell69382852017-07-21 16:38:44 -04001443 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001445 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001446 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001447 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001449 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001451 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001452 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001453 }
Geoff Lange4915782017-04-12 15:19:07 -04001454
1455 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001457 context->handleError(
1458 InvalidOperation()
1459 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001460 return false;
1461 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001462 }
He Yunchao66a41a22016-12-15 16:45:05 +08001463 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1464 else if (drawBuffer)
1465 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001466 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1467 "depth/stencil attachment of a "
1468 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001469 return false;
1470 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001471 }
1472 }
1473
Martin Radeva3ed4572017-07-27 18:29:37 +03001474 // ANGLE_multiview, Revision 1:
1475 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1476 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1477 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1478 {
1479 context->handleError(InvalidFramebufferOperation()
1480 << "Attempt to read from a multi-view framebuffer.");
1481 return false;
1482 }
1483 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1484 {
1485 context->handleError(InvalidFramebufferOperation()
1486 << "Attempt to write to a multi-view framebuffer.");
1487 return false;
1488 }
1489
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001490 return true;
1491}
1492
Jamie Madill4928b7c2017-06-20 12:57:39 -04001493bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001494 GLint x,
1495 GLint y,
1496 GLsizei width,
1497 GLsizei height,
1498 GLenum format,
1499 GLenum type,
1500 GLsizei bufSize,
1501 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001502 GLsizei *columns,
1503 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001504 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001505{
1506 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001507 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001508 return false;
1509 }
1510
Brandon Jonesd1049182018-03-28 10:02:20 -07001511 GLsizei writeLength = 0;
1512 GLsizei writeColumns = 0;
1513 GLsizei writeRows = 0;
1514
1515 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1516 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001517 {
Geoff Langb1196682014-07-23 13:47:29 -04001518 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001519 }
1520
Brandon Jonesd1049182018-03-28 10:02:20 -07001521 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001522 {
Geoff Langb1196682014-07-23 13:47:29 -04001523 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001524 }
1525
Brandon Jonesd1049182018-03-28 10:02:20 -07001526 SetRobustLengthParam(length, writeLength);
1527 SetRobustLengthParam(columns, writeColumns);
1528 SetRobustLengthParam(rows, writeRows);
1529
Jamie Madillc29968b2016-01-20 11:17:23 -05001530 return true;
1531}
1532
1533bool ValidateReadnPixelsEXT(Context *context,
1534 GLint x,
1535 GLint y,
1536 GLsizei width,
1537 GLsizei height,
1538 GLenum format,
1539 GLenum type,
1540 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001541 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001542{
1543 if (bufSize < 0)
1544 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001545 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001546 return false;
1547 }
1548
Geoff Lang62fce5b2016-09-30 10:46:35 -04001549 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001550 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001551}
Jamie Madill26e91952014-03-05 15:01:27 -05001552
Jamie Madill4928b7c2017-06-20 12:57:39 -04001553bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001554 GLint x,
1555 GLint y,
1556 GLsizei width,
1557 GLsizei height,
1558 GLenum format,
1559 GLenum type,
1560 GLsizei bufSize,
1561 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001562 GLsizei *columns,
1563 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001564 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001565{
Brandon Jonesd1049182018-03-28 10:02:20 -07001566 GLsizei writeLength = 0;
1567 GLsizei writeColumns = 0;
1568 GLsizei writeRows = 0;
1569
Geoff Lang62fce5b2016-09-30 10:46:35 -04001570 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001571 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001572 return false;
1573 }
1574
Brandon Jonesd1049182018-03-28 10:02:20 -07001575 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1576 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001577 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001578 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001579 }
1580
Brandon Jonesd1049182018-03-28 10:02:20 -07001581 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001582 {
1583 return false;
1584 }
1585
Brandon Jonesd1049182018-03-28 10:02:20 -07001586 SetRobustLengthParam(length, writeLength);
1587 SetRobustLengthParam(columns, writeColumns);
1588 SetRobustLengthParam(rows, writeRows);
1589
Geoff Lang62fce5b2016-09-30 10:46:35 -04001590 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001591}
1592
Jamie Madillf0e04492017-08-26 15:28:42 -04001593bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001594{
1595 if (!context->getExtensions().occlusionQueryBoolean &&
1596 !context->getExtensions().disjointTimerQuery)
1597 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001598 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001599 return false;
1600 }
1601
Olli Etuaho41997e72016-03-10 13:38:39 +02001602 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001603}
1604
Jamie Madillf0e04492017-08-26 15:28:42 -04001605bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001606{
1607 if (!context->getExtensions().occlusionQueryBoolean &&
1608 !context->getExtensions().disjointTimerQuery)
1609 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001610 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001611 return false;
1612 }
1613
Olli Etuaho41997e72016-03-10 13:38:39 +02001614 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001615}
1616
Jamie Madillf0e04492017-08-26 15:28:42 -04001617bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1618{
1619 if (!context->getExtensions().occlusionQueryBoolean &&
1620 !context->getExtensions().disjointTimerQuery)
1621 {
1622 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1623 return false;
1624 }
1625
1626 return true;
1627}
1628
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001629bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001630{
1631 if (!ValidQueryType(context, target))
1632 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001633 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001634 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001635 }
1636
1637 if (id == 0)
1638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001639 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001640 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001641 }
1642
1643 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1644 // of zero, if the active query object name for <target> is non-zero (for the
1645 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1646 // the active query for either target is non-zero), if <id> is the name of an
1647 // existing query object whose type does not match <target>, or if <id> is the
1648 // active query object name for any query type, the error INVALID_OPERATION is
1649 // generated.
1650
1651 // Ensure no other queries are active
1652 // NOTE: If other queries than occlusion are supported, we will need to check
1653 // separately that:
1654 // a) The query ID passed is not the current active query for any target/type
1655 // b) There are no active queries for the requested target (and in the case
1656 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1657 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001658
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001659 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001661 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001662 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001663 }
1664
1665 Query *queryObject = context->getQuery(id, true, target);
1666
1667 // check that name was obtained with glGenQueries
1668 if (!queryObject)
1669 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001670 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001671 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001672 }
1673
1674 // check for type mismatch
1675 if (queryObject->getType() != target)
1676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001677 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001678 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001679 }
1680
1681 return true;
1682}
1683
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1685{
1686 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001687 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001688 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001689 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001690 return false;
1691 }
1692
1693 return ValidateBeginQueryBase(context, target, id);
1694}
1695
1696bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001697{
1698 if (!ValidQueryType(context, target))
1699 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001700 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001701 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001702 }
1703
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001704 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001705
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001706 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001708 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001709 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001710 }
1711
Jamie Madill45c785d2014-05-13 14:09:34 -04001712 return true;
1713}
1714
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1716{
1717 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001718 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001719 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001720 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 return false;
1722 }
1723
1724 return ValidateEndQueryBase(context, target);
1725}
1726
1727bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1728{
1729 if (!context->getExtensions().disjointTimerQuery)
1730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001731 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 return false;
1733 }
1734
1735 if (target != GL_TIMESTAMP_EXT)
1736 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001737 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001738 return false;
1739 }
1740
1741 Query *queryObject = context->getQuery(id, true, target);
1742 if (queryObject == nullptr)
1743 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001744 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001745 return false;
1746 }
1747
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001748 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001749 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001750 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001751 return false;
1752 }
1753
1754 return true;
1755}
1756
Geoff Lang2186c382016-10-14 10:54:54 -04001757bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758{
Geoff Lang2186c382016-10-14 10:54:54 -04001759 if (numParams)
1760 {
1761 *numParams = 0;
1762 }
1763
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001764 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1765 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001766 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767 return false;
1768 }
1769
1770 switch (pname)
1771 {
1772 case GL_CURRENT_QUERY_EXT:
1773 if (target == GL_TIMESTAMP_EXT)
1774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001775 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001776 return false;
1777 }
1778 break;
1779 case GL_QUERY_COUNTER_BITS_EXT:
1780 if (!context->getExtensions().disjointTimerQuery ||
1781 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1782 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001783 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001784 return false;
1785 }
1786 break;
1787 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001788 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001789 return false;
1790 }
1791
Geoff Lang2186c382016-10-14 10:54:54 -04001792 if (numParams)
1793 {
1794 // All queries return only one value
1795 *numParams = 1;
1796 }
1797
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001798 return true;
1799}
1800
1801bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1802{
1803 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001804 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001805 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001807 return false;
1808 }
1809
Geoff Lang2186c382016-10-14 10:54:54 -04001810 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001811}
1812
Geoff Lang2186c382016-10-14 10:54:54 -04001813bool ValidateGetQueryivRobustANGLE(Context *context,
1814 GLenum target,
1815 GLenum pname,
1816 GLsizei bufSize,
1817 GLsizei *length,
1818 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819{
Geoff Lang2186c382016-10-14 10:54:54 -04001820 if (!ValidateRobustEntryPoint(context, bufSize))
1821 {
1822 return false;
1823 }
1824
Brandon Jonesd1049182018-03-28 10:02:20 -07001825 GLsizei numParams = 0;
1826
1827 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001828 {
1829 return false;
1830 }
1831
Brandon Jonesd1049182018-03-28 10:02:20 -07001832 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001833 {
1834 return false;
1835 }
1836
Brandon Jonesd1049182018-03-28 10:02:20 -07001837 SetRobustLengthParam(length, numParams);
1838
Geoff Lang2186c382016-10-14 10:54:54 -04001839 return true;
1840}
1841
1842bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1843{
1844 if (numParams)
1845 {
1846 *numParams = 0;
1847 }
1848
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001849 Query *queryObject = context->getQuery(id, false, GL_NONE);
1850
1851 if (!queryObject)
1852 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001853 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001854 return false;
1855 }
1856
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001857 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001858 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001859 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001860 return false;
1861 }
1862
1863 switch (pname)
1864 {
1865 case GL_QUERY_RESULT_EXT:
1866 case GL_QUERY_RESULT_AVAILABLE_EXT:
1867 break;
1868
1869 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001870 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001871 return false;
1872 }
1873
Geoff Lang2186c382016-10-14 10:54:54 -04001874 if (numParams)
1875 {
1876 *numParams = 1;
1877 }
1878
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001879 return true;
1880}
1881
1882bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1883{
1884 if (!context->getExtensions().disjointTimerQuery)
1885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001886 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001887 return false;
1888 }
Geoff Lang2186c382016-10-14 10:54:54 -04001889 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1890}
1891
1892bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1893 GLuint id,
1894 GLenum pname,
1895 GLsizei bufSize,
1896 GLsizei *length,
1897 GLint *params)
1898{
1899 if (!context->getExtensions().disjointTimerQuery)
1900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001901 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001902 return false;
1903 }
1904
1905 if (!ValidateRobustEntryPoint(context, bufSize))
1906 {
1907 return false;
1908 }
1909
Brandon Jonesd1049182018-03-28 10:02:20 -07001910 GLsizei numParams = 0;
1911
1912 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001913 {
1914 return false;
1915 }
1916
Brandon Jonesd1049182018-03-28 10:02:20 -07001917 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001918 {
1919 return false;
1920 }
1921
Brandon Jonesd1049182018-03-28 10:02:20 -07001922 SetRobustLengthParam(length, numParams);
1923
Geoff Lang2186c382016-10-14 10:54:54 -04001924 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925}
1926
1927bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1928{
1929 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001930 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001932 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001933 return false;
1934 }
Geoff Lang2186c382016-10-14 10:54:54 -04001935 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1936}
1937
1938bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1939 GLuint id,
1940 GLenum pname,
1941 GLsizei bufSize,
1942 GLsizei *length,
1943 GLuint *params)
1944{
1945 if (!context->getExtensions().disjointTimerQuery &&
1946 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1947 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001948 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001949 return false;
1950 }
1951
1952 if (!ValidateRobustEntryPoint(context, bufSize))
1953 {
1954 return false;
1955 }
1956
Brandon Jonesd1049182018-03-28 10:02:20 -07001957 GLsizei numParams = 0;
1958
1959 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001960 {
1961 return false;
1962 }
1963
Brandon Jonesd1049182018-03-28 10:02:20 -07001964 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001965 {
1966 return false;
1967 }
1968
Brandon Jonesd1049182018-03-28 10:02:20 -07001969 SetRobustLengthParam(length, numParams);
1970
Geoff Lang2186c382016-10-14 10:54:54 -04001971 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001972}
1973
1974bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1975{
1976 if (!context->getExtensions().disjointTimerQuery)
1977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001978 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001979 return false;
1980 }
Geoff Lang2186c382016-10-14 10:54:54 -04001981 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1982}
1983
1984bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1985 GLuint id,
1986 GLenum pname,
1987 GLsizei bufSize,
1988 GLsizei *length,
1989 GLint64 *params)
1990{
1991 if (!context->getExtensions().disjointTimerQuery)
1992 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001994 return false;
1995 }
1996
1997 if (!ValidateRobustEntryPoint(context, bufSize))
1998 {
1999 return false;
2000 }
2001
Brandon Jonesd1049182018-03-28 10:02:20 -07002002 GLsizei numParams = 0;
2003
2004 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002005 {
2006 return false;
2007 }
2008
Brandon Jonesd1049182018-03-28 10:02:20 -07002009 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002010 {
2011 return false;
2012 }
2013
Brandon Jonesd1049182018-03-28 10:02:20 -07002014 SetRobustLengthParam(length, numParams);
2015
Geoff Lang2186c382016-10-14 10:54:54 -04002016 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002017}
2018
2019bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2020{
2021 if (!context->getExtensions().disjointTimerQuery)
2022 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002023 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002024 return false;
2025 }
Geoff Lang2186c382016-10-14 10:54:54 -04002026 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2027}
2028
2029bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2030 GLuint id,
2031 GLenum pname,
2032 GLsizei bufSize,
2033 GLsizei *length,
2034 GLuint64 *params)
2035{
2036 if (!context->getExtensions().disjointTimerQuery)
2037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002039 return false;
2040 }
2041
2042 if (!ValidateRobustEntryPoint(context, bufSize))
2043 {
2044 return false;
2045 }
2046
Brandon Jonesd1049182018-03-28 10:02:20 -07002047 GLsizei numParams = 0;
2048
2049 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002050 {
2051 return false;
2052 }
2053
Brandon Jonesd1049182018-03-28 10:02:20 -07002054 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002055 {
2056 return false;
2057 }
2058
Brandon Jonesd1049182018-03-28 10:02:20 -07002059 SetRobustLengthParam(length, numParams);
2060
Geoff Lang2186c382016-10-14 10:54:54 -04002061 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002062}
2063
Jamie Madill5b772312018-03-08 20:28:32 -05002064bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002065 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002066 GLint location,
2067 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002068 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002069{
Jiajia Qin5451d532017-11-16 17:16:34 +08002070 // TODO(Jiajia): Add image uniform check in future.
2071 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002072 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002073 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002074 return false;
2075 }
2076
Jiajia Qin5451d532017-11-16 17:16:34 +08002077 if (!program)
2078 {
2079 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2080 return false;
2081 }
2082
2083 if (!program->isLinked())
2084 {
2085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2086 return false;
2087 }
2088
2089 if (location == -1)
2090 {
2091 // Silently ignore the uniform command
2092 return false;
2093 }
2094
2095 const auto &uniformLocations = program->getUniformLocations();
2096 size_t castedLocation = static_cast<size_t>(location);
2097 if (castedLocation >= uniformLocations.size())
2098 {
2099 context->handleError(InvalidOperation() << "Invalid uniform location");
2100 return false;
2101 }
2102
2103 const auto &uniformLocation = uniformLocations[castedLocation];
2104 if (uniformLocation.ignored)
2105 {
2106 // Silently ignore the uniform command
2107 return false;
2108 }
2109
2110 if (!uniformLocation.used())
2111 {
2112 context->handleError(InvalidOperation());
2113 return false;
2114 }
2115
2116 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2117
2118 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2119 if (!uniform.isArray() && count > 1)
2120 {
2121 context->handleError(InvalidOperation());
2122 return false;
2123 }
2124
2125 *uniformOut = &uniform;
2126 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002127}
2128
Jamie Madill5b772312018-03-08 20:28:32 -05002129bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002130 GLenum uniformType,
2131 GLsizei count,
2132 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002133{
Jiajia Qin5451d532017-11-16 17:16:34 +08002134 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2135 // It is compatible with INT or BOOL.
2136 // Do these cheap tests first, for a little extra speed.
2137 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002138 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002139 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002140 }
2141
Jiajia Qin5451d532017-11-16 17:16:34 +08002142 if (IsSamplerType(uniformType))
2143 {
2144 // Check that the values are in range.
2145 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2146 for (GLsizei i = 0; i < count; ++i)
2147 {
2148 if (value[i] < 0 || value[i] >= max)
2149 {
2150 context->handleError(InvalidValue() << "sampler uniform value out of range");
2151 return false;
2152 }
2153 }
2154 return true;
2155 }
2156
2157 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2158 return false;
2159}
2160
Jamie Madill5b772312018-03-08 20:28:32 -05002161bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002162{
2163 // Check that the value type is compatible with uniform type.
2164 // Do the cheaper test first, for a little extra speed.
2165 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2166 {
2167 return true;
2168 }
2169
2170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2171 return false;
2172}
2173
Jamie Madill5b772312018-03-08 20:28:32 -05002174bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002175{
2176 // Check that the value type is compatible with uniform type.
2177 if (valueType == uniformType)
2178 {
2179 return true;
2180 }
2181
2182 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2183 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002184}
2185
Jamie Madill5b772312018-03-08 20:28:32 -05002186bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002187{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002188 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002189 gl::Program *programObject = context->getGLState().getProgram();
2190 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2191 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002192}
2193
Jamie Madill5b772312018-03-08 20:28:32 -05002194bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002195{
2196 const LinkedUniform *uniform = nullptr;
2197 gl::Program *programObject = context->getGLState().getProgram();
2198 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2199 ValidateUniform1ivValue(context, uniform->type, count, value);
2200}
2201
Jamie Madill5b772312018-03-08 20:28:32 -05002202bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002203 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002204 GLint location,
2205 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002206 GLboolean transpose)
2207{
Geoff Lang92019432017-11-20 13:09:34 -05002208 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002210 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002211 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002212 }
2213
Jamie Madill62d31cb2015-09-11 13:25:51 -04002214 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002215 gl::Program *programObject = context->getGLState().getProgram();
2216 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2217 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002218}
2219
Jamie Madill5b772312018-03-08 20:28:32 -05002220bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002221{
2222 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002224 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002225 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002226 }
2227
Jamie Madill0af26e12015-03-05 19:54:33 -05002228 const Caps &caps = context->getCaps();
2229
Jamie Madill893ab082014-05-16 16:56:10 -04002230 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2231 {
2232 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2233
Jamie Madill0af26e12015-03-05 19:54:33 -05002234 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002236 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002237 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002238 }
2239 }
2240
2241 switch (pname)
2242 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002243 case GL_TEXTURE_BINDING_2D:
2244 case GL_TEXTURE_BINDING_CUBE_MAP:
2245 case GL_TEXTURE_BINDING_3D:
2246 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002247 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002248 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002249 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2250 if (!context->getExtensions().textureRectangle)
2251 {
2252 context->handleError(InvalidEnum()
2253 << "ANGLE_texture_rectangle extension not present");
2254 return false;
2255 }
2256 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002257 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2258 if (!context->getExtensions().eglStreamConsumerExternal &&
2259 !context->getExtensions().eglImageExternal)
2260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002261 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2262 "nor GL_OES_EGL_image_external "
2263 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002264 return false;
2265 }
2266 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002267
He Yunchaoced53ae2016-11-29 15:00:51 +08002268 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2269 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002270 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002271 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2272 ASSERT(readFramebuffer);
2273
Jamie Madill427064d2018-04-13 16:20:34 -04002274 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002275 {
Geoff Langb1196682014-07-23 13:47:29 -04002276 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002277 }
2278
Jamie Madille98b1b52018-03-08 09:47:23 -05002279 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002280 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002281 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002282 return false;
2283 }
2284
Jamie Madille98b1b52018-03-08 09:47:23 -05002285 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002286 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002288 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002289 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002290 }
2291 }
2292 break;
2293
He Yunchaoced53ae2016-11-29 15:00:51 +08002294 default:
2295 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002296 }
2297
2298 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002299 if (*numParams == 0)
2300 {
2301 return false;
2302 }
2303
2304 return true;
2305}
2306
Brandon Jonesd1049182018-03-28 10:02:20 -07002307bool ValidateGetBooleanvRobustANGLE(Context *context,
2308 GLenum pname,
2309 GLsizei bufSize,
2310 GLsizei *length,
2311 GLboolean *params)
2312{
2313 GLenum nativeType;
2314 unsigned int numParams = 0;
2315
2316 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2317 {
2318 return false;
2319 }
2320
2321 SetRobustLengthParam(length, numParams);
2322
2323 return true;
2324}
2325
2326bool ValidateGetFloatvRobustANGLE(Context *context,
2327 GLenum pname,
2328 GLsizei bufSize,
2329 GLsizei *length,
2330 GLfloat *params)
2331{
2332 GLenum nativeType;
2333 unsigned int numParams = 0;
2334
2335 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2336 {
2337 return false;
2338 }
2339
2340 SetRobustLengthParam(length, numParams);
2341
2342 return true;
2343}
2344
2345bool ValidateGetIntegervRobustANGLE(Context *context,
2346 GLenum pname,
2347 GLsizei bufSize,
2348 GLsizei *length,
2349 GLint *data)
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 ValidateGetInteger64vRobustANGLE(Context *context,
2365 GLenum pname,
2366 GLsizei bufSize,
2367 GLsizei *length,
2368 GLint64 *data)
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 if (nativeType == GL_INT_64_ANGLEX)
2379 {
2380 CastStateValues(context, nativeType, pname, numParams, data);
2381 return false;
2382 }
2383
2384 SetRobustLengthParam(length, numParams);
2385 return true;
2386}
2387
Jamie Madill5b772312018-03-08 20:28:32 -05002388bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002389 GLenum pname,
2390 GLsizei bufSize,
2391 GLenum *nativeType,
2392 unsigned int *numParams)
2393{
2394 if (!ValidateRobustEntryPoint(context, bufSize))
2395 {
2396 return false;
2397 }
2398
2399 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2400 {
2401 return false;
2402 }
2403
2404 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002405 {
2406 return false;
2407 }
2408
2409 return true;
2410}
2411
Jamie Madill5b772312018-03-08 20:28:32 -05002412bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002413 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002414 GLint level,
2415 GLenum internalformat,
2416 bool isSubImage,
2417 GLint xoffset,
2418 GLint yoffset,
2419 GLint zoffset,
2420 GLint x,
2421 GLint y,
2422 GLsizei width,
2423 GLsizei height,
2424 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002425 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002426{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002427 TextureType texType = TextureTargetToType(target);
2428
Brandon Jones6cad5662017-06-14 13:25:13 -07002429 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002430 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002431 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2432 return false;
2433 }
2434
2435 if (width < 0 || height < 0)
2436 {
2437 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002438 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002439 }
2440
He Yunchaoced53ae2016-11-29 15:00:51 +08002441 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2442 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002444 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002445 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002446 }
2447
2448 if (border != 0)
2449 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002450 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002451 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002452 }
2453
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002454 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002455 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002456 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002457 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002458 }
2459
Jamie Madille98b1b52018-03-08 09:47:23 -05002460 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002461 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002462 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002463 {
Geoff Langb1196682014-07-23 13:47:29 -04002464 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002465 }
2466
Jamie Madille98b1b52018-03-08 09:47:23 -05002467 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002468 {
Geoff Langb1196682014-07-23 13:47:29 -04002469 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002470 }
2471
Martin Radev138064f2016-07-15 12:03:41 +03002472 if (readFramebuffer->getReadBufferState() == GL_NONE)
2473 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002475 return false;
2476 }
2477
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002478 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2479 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002480 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002481 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002482 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2483 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002484 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002485 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002486 return false;
2487 }
2488
Martin Radev04e2c3b2017-07-27 16:54:35 +03002489 // ANGLE_multiview spec, Revision 1:
2490 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2491 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2492 // is not NONE.
2493 if (source->getMultiviewLayout() != GL_NONE)
2494 {
2495 context->handleError(InvalidFramebufferOperation()
2496 << "The active read framebuffer object has multiview attachments.");
2497 return false;
2498 }
2499
Geoff Langaae65a42014-05-26 12:43:44 -04002500 const gl::Caps &caps = context->getCaps();
2501
Geoff Langaae65a42014-05-26 12:43:44 -04002502 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002503 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002504 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002505 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002506 maxDimension = caps.max2DTextureSize;
2507 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002508
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002509 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002510 maxDimension = caps.maxCubeMapTextureSize;
2511 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002512
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002513 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002514 maxDimension = caps.maxRectangleTextureSize;
2515 break;
2516
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002517 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002518 maxDimension = caps.max2DTextureSize;
2519 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002520
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002521 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002522 maxDimension = caps.max3DTextureSize;
2523 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002524
He Yunchaoced53ae2016-11-29 15:00:51 +08002525 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002526 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002527 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002528 }
2529
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002530 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002531 if (!texture)
2532 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002533 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002534 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002535 }
2536
Geoff Lang69cce582015-09-17 13:20:36 -04002537 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002539 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002540 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002541 }
2542
Geoff Langca271392017-04-05 12:30:00 -04002543 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002544 isSubImage ? *texture->getFormat(target, level).info
2545 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002546
Geoff Lang966c9402017-04-18 12:38:27 -04002547 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002548 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002549 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002550 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002551 }
2552
2553 if (isSubImage)
2554 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002555 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2556 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2557 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002559 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002560 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002561 }
2562 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002563 else
2564 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002565 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002566 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002567 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002568 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002569 }
2570
Geoff Langeb66a6e2016-10-31 13:06:12 -04002571 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002574 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002575 }
2576
2577 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002578 if (static_cast<int>(width) > maxLevelDimension ||
2579 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002580 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002581 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002582 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002583 }
2584 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002585
Jamie Madill0c8abca2016-07-22 20:21:26 -04002586 if (textureFormatOut)
2587 {
2588 *textureFormatOut = texture->getFormat(target, level);
2589 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002590
2591 // Detect texture copying feedback loops for WebGL.
2592 if (context->getExtensions().webglCompatibility)
2593 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002594 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002595 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002597 return false;
2598 }
2599 }
2600
Jamie Madill560a8d82014-05-21 13:06:20 -04002601 return true;
2602}
2603
Jamie Madill5b772312018-03-08 20:28:32 -05002604bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002605{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002606 const Extensions &extensions = context->getExtensions();
2607
Jamie Madill1aeb1312014-06-20 13:21:25 -04002608 switch (mode)
2609 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002610 case GL_POINTS:
2611 case GL_LINES:
2612 case GL_LINE_LOOP:
2613 case GL_LINE_STRIP:
2614 case GL_TRIANGLES:
2615 case GL_TRIANGLE_STRIP:
2616 case GL_TRIANGLE_FAN:
2617 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002618
2619 case GL_LINES_ADJACENCY_EXT:
2620 case GL_LINE_STRIP_ADJACENCY_EXT:
2621 case GL_TRIANGLES_ADJACENCY_EXT:
2622 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2623 if (!extensions.geometryShader)
2624 {
2625 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2626 return false;
2627 }
2628 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002629 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002630 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002631 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002632 }
2633
Jamie Madill250d33f2014-06-06 17:09:03 -04002634 if (count < 0)
2635 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002636 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002637 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002638 }
2639
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002640 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002641
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002642 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2643 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2644 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2645 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002646 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002647 // Check for mapped buffers
2648 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002649 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002650 {
2651 context->handleError(InvalidOperation());
2652 return false;
2653 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002654 }
2655
Jamie Madillcbcde722017-01-06 14:50:00 -05002656 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2657 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002658 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002659 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002660 {
Ken Russellb9f92502018-01-27 19:00:26 -08002661 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002662 const FramebufferAttachment *dsAttachment =
2663 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002664 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2665 ASSERT(stencilBits <= 8);
2666
Jinyoung Hur85769f02015-10-20 17:08:44 -04002667 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002668 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002669 {
Ken Russellb9f92502018-01-27 19:00:26 -08002670 GLuint maxStencilValue = (1 << stencilBits) - 1;
2671
2672 bool differentRefs =
2673 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2674 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2675 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2676 (depthStencilState.stencilBackWritemask & maxStencilValue);
2677 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2678 (depthStencilState.stencilBackMask & maxStencilValue);
2679
2680 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002681 {
Ken Russellb9f92502018-01-27 19:00:26 -08002682 if (!extensions.webglCompatibility)
2683 {
2684 ERR() << "This ANGLE implementation does not support separate front/back "
2685 "stencil writemasks, reference values, or stencil mask values.";
2686 }
2687 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2688 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002689 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002690 }
Jamie Madillac528012014-06-20 13:21:23 -04002691 }
2692
Jamie Madill427064d2018-04-13 16:20:34 -04002693 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002694 {
Geoff Langb1196682014-07-23 13:47:29 -04002695 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002696 }
2697
Geoff Lang7dd2e102014-11-10 15:19:26 -05002698 gl::Program *program = state.getProgram();
2699 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002700 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002701 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002702 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002703 }
2704
Yunchao Hecddcb592017-11-13 15:27:35 +08002705 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2706 // vertex shader stage or fragment shader stage is a undefined behaviour.
2707 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2708 // produce undefined result.
Jiawei Shao385b3e02018-03-21 09:43:28 +08002709 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2710 !program->hasLinkedShaderStage(ShaderType::Fragment))
Yunchao Hecddcb592017-11-13 15:27:35 +08002711 {
2712 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2713 "vertex shader stage or fragment shader stage.");
2714 return false;
2715 }
2716
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002717 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002719 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002720 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002721 }
2722
Martin Radevffe754b2017-07-31 10:38:07 +03002723 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002724 {
Martin Radevda8e2572017-09-12 17:21:16 +03002725 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002726 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002727 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002728 {
2729 context->handleError(InvalidOperation() << "The number of views in the active program "
2730 "and draw framebuffer does not match.");
2731 return false;
2732 }
Martin Radev7e69f762017-07-27 14:54:13 +03002733
2734 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2735 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2736 framebufferNumViews > 1)
2737 {
2738 context->handleError(InvalidOperation()
2739 << "There is an active transform feedback object "
2740 "when the number of views in the active draw "
2741 "framebuffer is greater than 1.");
2742 return false;
2743 }
Martin Radevffe754b2017-07-31 10:38:07 +03002744
2745 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2746 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2747 {
2748 context->handleError(InvalidOperation() << "There is an active query for target "
2749 "GL_TIME_ELAPSED_EXT when the number of "
2750 "views in the active draw framebuffer is "
2751 "greater than 1.");
2752 return false;
2753 }
Martin Radev7cf61662017-07-26 17:10:53 +03002754 }
2755
Jiawei Shaofccebff2018-03-08 13:51:02 +08002756 // Do geometry shader specific validations
Jiawei Shao385b3e02018-03-21 09:43:28 +08002757 if (program->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shaofccebff2018-03-08 13:51:02 +08002758 {
2759 if (!IsCompatibleDrawModeWithGeometryShader(mode,
2760 program->getGeometryShaderInputPrimitiveType()))
2761 {
2762 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2763 IncompatibleDrawModeAgainstGeometryShader);
2764 return false;
2765 }
2766 }
2767
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002768 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002769 for (unsigned int uniformBlockIndex = 0;
2770 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002771 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002772 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Lingfeng Yang038dd532018-03-29 17:31:52 -07002773 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002774 const OffsetBindingPointer<Buffer> &uniformBuffer =
2775 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002776
Geoff Lang5d124a62015-09-15 13:03:27 -04002777 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002778 {
2779 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002780 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002781 InvalidOperation()
2782 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002783 return false;
2784 }
2785
James Darpinian30b604d2018-03-12 17:26:57 -07002786 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002787 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002788 {
2789 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002790 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002791 InvalidOperation()
2792 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002793 return false;
2794 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002795
2796 if (extensions.webglCompatibility &&
2797 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2798 {
2799 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2800 UniformBufferBoundForTransformFeedback);
2801 return false;
2802 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002803 }
2804
Geoff Lange0cff192017-05-30 13:04:56 -04002805 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002806 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002807 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002808 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2809 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2810 transformFeedbackObject->buffersBoundForOtherUse())
2811 {
2812 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2813 return false;
2814 }
Geoff Lange0cff192017-05-30 13:04:56 -04002815 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002816 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2817 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002818 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002819 return false;
2820 }
Geoff Lange0cff192017-05-30 13:04:56 -04002821
Geoff Lang9ab5b822017-05-30 16:19:23 -04002822 // Detect that the vertex shader input types match the attribute types
2823 if (!ValidateVertexShaderAttributeTypeMatch(context))
2824 {
2825 return false;
2826 }
2827
Geoff Lange0cff192017-05-30 13:04:56 -04002828 // Detect that the color buffer types match the fragment shader output types
2829 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2830 {
2831 return false;
2832 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002833 }
2834
Jamie Madill9fdaa492018-02-16 10:52:11 -05002835 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002836}
2837
Jamie Madill5b772312018-03-08 20:28:32 -05002838bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002839 GLenum mode,
2840 GLint first,
2841 GLsizei count,
2842 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002843{
Jamie Madillfd716582014-06-06 17:09:04 -04002844 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002845 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002846 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002847 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002848 }
2849
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002850 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002851 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002852 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002853 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002854 {
James Darpinian30b604d2018-03-12 17:26:57 -07002855 if (curTransformFeedback->getPrimitiveMode() != mode)
2856 {
2857 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2858 // that does not match the current transform feedback object's draw mode (if transform
2859 // feedback
2860 // is active), (3.0.2, section 2.14, pg 86)
2861 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2862 return false;
2863 }
2864
2865 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2866 {
2867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2868 return false;
2869 }
Jamie Madillfd716582014-06-06 17:09:04 -04002870 }
2871
Jiajia Qind9671222016-11-29 16:30:31 +08002872 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002873 {
2874 return false;
2875 }
2876
Corentin Wallez71168a02016-12-19 15:11:18 -08002877 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002878 // - first < 0 has been checked as an error condition.
2879 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002880 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002881 ASSERT(first >= 0);
2882 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002883 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002884 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2885 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2886 {
2887 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2888 return false;
2889 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002890
Jamie Madill9fdaa492018-02-16 10:52:11 -05002891 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2892 {
2893 return false;
2894 }
Jamie Madillfd716582014-06-06 17:09:04 -04002895 }
2896
2897 return true;
2898}
2899
He Yunchaoced53ae2016-11-29 15:00:51 +08002900bool ValidateDrawArraysInstancedANGLE(Context *context,
2901 GLenum mode,
2902 GLint first,
2903 GLsizei count,
2904 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002905{
Geoff Lang63c5a592017-09-27 14:08:16 -04002906 if (!context->getExtensions().instancedArrays)
2907 {
2908 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2909 return false;
2910 }
2911
Corentin Wallez170efbf2017-05-02 13:45:01 -04002912 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002913 {
2914 return false;
2915 }
2916
Corentin Wallez0dc97812017-06-22 14:38:44 -04002917 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002918}
2919
Jamie Madill5b772312018-03-08 20:28:32 -05002920bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002921{
Jamie Madill250d33f2014-06-06 17:09:03 -04002922 switch (type)
2923 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002924 case GL_UNSIGNED_BYTE:
2925 case GL_UNSIGNED_SHORT:
2926 break;
2927 case GL_UNSIGNED_INT:
2928 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2929 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002930 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002931 return false;
2932 }
2933 break;
2934 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002935 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002936 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002937 }
2938
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002939 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002940
2941 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002942 if (curTransformFeedback && curTransformFeedback->isActive() &&
2943 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002944 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002945 // It is an invalid operation to call DrawElements, DrawRangeElements or
2946 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002947 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002948 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002949 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002950 }
2951
Jiajia Qind9671222016-11-29 16:30:31 +08002952 return true;
2953}
2954
Jamie Madill5b772312018-03-08 20:28:32 -05002955bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002956 GLenum mode,
2957 GLsizei count,
2958 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002959 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002960 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002961{
2962 if (!ValidateDrawElementsBase(context, type))
2963 return false;
2964
2965 const State &state = context->getGLState();
2966
Corentin Wallez170efbf2017-05-02 13:45:01 -04002967 if (!ValidateDrawBase(context, mode, count))
2968 {
2969 return false;
2970 }
2971
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002972 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2973 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2974 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2975 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002976 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002977 // Check for mapped buffers
2978 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002979 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002980 {
2981 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2982 return false;
2983 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002984 }
2985
He Yunchaoced53ae2016-11-29 15:00:51 +08002986 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002987 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002988
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002989 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2990
2991 if (context->getExtensions().webglCompatibility)
2992 {
2993 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2994 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2995 {
2996 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2997 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2998 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002999 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003000 return false;
3001 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003002
3003 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3004 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3005 // error is generated.
3006 if (reinterpret_cast<intptr_t>(indices) < 0)
3007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003008 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003009 return false;
3010 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003011 }
3012
3013 if (context->getExtensions().webglCompatibility ||
3014 !context->getGLState().areClientArraysEnabled())
3015 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003016 if (!elementArrayBuffer && count > 0)
3017 {
3018 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3019 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3020 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003021 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003022 return false;
3023 }
3024 }
3025
Jamie Madill9fdaa492018-02-16 10:52:11 -05003026 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003027 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003028 // This is an application error that would normally result in a crash, but we catch it and
3029 // return an error
3030 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3031 return false;
3032 }
3033
3034 if (count > 0 && elementArrayBuffer)
3035 {
3036 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3037 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3038 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3039 constexpr uint64_t kMaxTypeSize = 8;
3040 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3041 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3042 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3043
3044 uint64_t typeSize = typeBytes;
3045 uint64_t elementCount = static_cast<uint64_t>(count);
3046 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3047
3048 // Doing the multiplication here is overflow-safe
3049 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3050
3051 // The offset can be any value, check for overflows
3052 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3053 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003054 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3056 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003057 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003058
3059 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3060 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003061 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3063 return false;
3064 }
3065
3066 ASSERT(isPow2(typeSize) && typeSize > 0);
3067 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3068 {
3069 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003070 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003071 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003072
3073 if (context->getExtensions().webglCompatibility &&
3074 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3075 {
3076 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3077 ElementArrayBufferBoundForTransformFeedback);
3078 return false;
3079 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003080 }
3081
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003082 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003083 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003084 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3085 // access is enabled.
3086 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3087 {
3088 return false;
3089 }
3090 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003091 else if (count == 0)
3092 {
3093 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3094 // count.
3095 if (!ValidateDrawAttribs(context, 0, 0, 0))
3096 {
3097 return false;
3098 }
3099 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003100 else
3101 {
3102 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003103 const DrawCallParams &params = context->getParams<DrawCallParams>();
3104 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3105 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003106
3107 // If we use an index greater than our maximum supported index range, return an error.
3108 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3109 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003110 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003111 {
3112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3113 return false;
3114 }
3115
Jamie Madill6f5444d2018-03-14 10:08:11 -04003116 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3117 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003118 {
3119 return false;
3120 }
3121
3122 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003123 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003124 }
3125
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003126 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003127}
3128
Jamie Madill5b772312018-03-08 20:28:32 -05003129bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003130 GLenum mode,
3131 GLsizei count,
3132 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003133 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003134 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003135{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003136 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003137}
3138
Geoff Lang3edfe032015-09-04 16:38:24 -04003139bool ValidateDrawElementsInstancedANGLE(Context *context,
3140 GLenum mode,
3141 GLsizei count,
3142 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003143 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003144 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003145{
Geoff Lang63c5a592017-09-27 14:08:16 -04003146 if (!context->getExtensions().instancedArrays)
3147 {
3148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3149 return false;
3150 }
3151
Corentin Wallez170efbf2017-05-02 13:45:01 -04003152 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003153 {
3154 return false;
3155 }
3156
Corentin Wallez0dc97812017-06-22 14:38:44 -04003157 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003158}
3159
He Yunchaoced53ae2016-11-29 15:00:51 +08003160bool ValidateFramebufferTextureBase(Context *context,
3161 GLenum target,
3162 GLenum attachment,
3163 GLuint texture,
3164 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003165{
Geoff Lange8afa902017-09-27 15:00:43 -04003166 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003169 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003170 }
3171
3172 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003173 {
3174 return false;
3175 }
3176
Jamie Madill55ec3b12014-07-03 10:38:57 -04003177 if (texture != 0)
3178 {
3179 gl::Texture *tex = context->getTexture(texture);
3180
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003181 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003183 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003184 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003185 }
3186
3187 if (level < 0)
3188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003189 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003190 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003191 }
3192 }
3193
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003194 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003195 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003196
Jamie Madill84115c92015-04-23 15:00:07 -04003197 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003198 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003200 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003201 }
3202
3203 return true;
3204}
3205
Geoff Langb1196682014-07-23 13:47:29 -04003206bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003207{
3208 if (program == 0)
3209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003210 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003211 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003212 }
3213
Dian Xiang769769a2015-09-09 15:20:08 -07003214 gl::Program *programObject = GetValidProgram(context, program);
3215 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003216 {
3217 return false;
3218 }
3219
Jamie Madill0063c512014-08-25 15:47:53 -04003220 if (!programObject || !programObject->isLinked())
3221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003223 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003224 }
3225
Geoff Lang7dd2e102014-11-10 15:19:26 -05003226 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003228 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003229 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003230 }
3231
Jamie Madill0063c512014-08-25 15:47:53 -04003232 return true;
3233}
3234
Geoff Langf41d0ee2016-10-07 13:04:23 -04003235static bool ValidateSizedGetUniform(Context *context,
3236 GLuint program,
3237 GLint location,
3238 GLsizei bufSize,
3239 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003240{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003241 if (length)
3242 {
3243 *length = 0;
3244 }
3245
Jamie Madill78f41802014-08-25 15:47:55 -04003246 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003247 {
Jamie Madill78f41802014-08-25 15:47:55 -04003248 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003249 }
3250
Geoff Langf41d0ee2016-10-07 13:04:23 -04003251 if (bufSize < 0)
3252 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003253 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003254 return false;
3255 }
3256
Jamie Madilla502c742014-08-28 17:19:13 -04003257 gl::Program *programObject = context->getProgram(program);
3258 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003259
Jamie Madill78f41802014-08-25 15:47:55 -04003260 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003261 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003262 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003263 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003264 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003266 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003267 }
3268
Geoff Langf41d0ee2016-10-07 13:04:23 -04003269 if (length)
3270 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003271 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003272 }
3273
Jamie Madill0063c512014-08-25 15:47:53 -04003274 return true;
3275}
3276
He Yunchaoced53ae2016-11-29 15:00:51 +08003277bool ValidateGetnUniformfvEXT(Context *context,
3278 GLuint program,
3279 GLint location,
3280 GLsizei bufSize,
3281 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003282{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003283 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003284}
3285
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003286bool ValidateGetnUniformfvRobustANGLE(Context *context,
3287 GLuint program,
3288 GLint location,
3289 GLsizei bufSize,
3290 GLsizei *length,
3291 GLfloat *params)
3292{
3293 UNIMPLEMENTED();
3294 return false;
3295}
3296
He Yunchaoced53ae2016-11-29 15:00:51 +08003297bool ValidateGetnUniformivEXT(Context *context,
3298 GLuint program,
3299 GLint location,
3300 GLsizei bufSize,
3301 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003302{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003303 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3304}
3305
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003306bool ValidateGetnUniformivRobustANGLE(Context *context,
3307 GLuint program,
3308 GLint location,
3309 GLsizei bufSize,
3310 GLsizei *length,
3311 GLint *params)
3312{
3313 UNIMPLEMENTED();
3314 return false;
3315}
3316
3317bool ValidateGetnUniformuivRobustANGLE(Context *context,
3318 GLuint program,
3319 GLint location,
3320 GLsizei bufSize,
3321 GLsizei *length,
3322 GLuint *params)
3323{
3324 UNIMPLEMENTED();
3325 return false;
3326}
3327
Geoff Langf41d0ee2016-10-07 13:04:23 -04003328bool ValidateGetUniformfvRobustANGLE(Context *context,
3329 GLuint program,
3330 GLint location,
3331 GLsizei bufSize,
3332 GLsizei *length,
3333 GLfloat *params)
3334{
3335 if (!ValidateRobustEntryPoint(context, bufSize))
3336 {
3337 return false;
3338 }
3339
Brandon Jonesd1049182018-03-28 10:02:20 -07003340 GLsizei writeLength = 0;
3341
Geoff Langf41d0ee2016-10-07 13:04:23 -04003342 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003343 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3344 {
3345 return false;
3346 }
3347
3348 SetRobustLengthParam(length, writeLength);
3349
3350 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003351}
3352
3353bool ValidateGetUniformivRobustANGLE(Context *context,
3354 GLuint program,
3355 GLint location,
3356 GLsizei bufSize,
3357 GLsizei *length,
3358 GLint *params)
3359{
3360 if (!ValidateRobustEntryPoint(context, bufSize))
3361 {
3362 return false;
3363 }
3364
Brandon Jonesd1049182018-03-28 10:02:20 -07003365 GLsizei writeLength = 0;
3366
Geoff Langf41d0ee2016-10-07 13:04:23 -04003367 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003368 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3369 {
3370 return false;
3371 }
3372
3373 SetRobustLengthParam(length, writeLength);
3374
3375 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003376}
3377
3378bool ValidateGetUniformuivRobustANGLE(Context *context,
3379 GLuint program,
3380 GLint location,
3381 GLsizei bufSize,
3382 GLsizei *length,
3383 GLuint *params)
3384{
3385 if (!ValidateRobustEntryPoint(context, bufSize))
3386 {
3387 return false;
3388 }
3389
3390 if (context->getClientMajorVersion() < 3)
3391 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003392 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003393 return false;
3394 }
3395
Brandon Jonesd1049182018-03-28 10:02:20 -07003396 GLsizei writeLength = 0;
3397
Geoff Langf41d0ee2016-10-07 13:04:23 -04003398 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003399 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3400 {
3401 return false;
3402 }
3403
3404 SetRobustLengthParam(length, writeLength);
3405
3406 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003407}
3408
He Yunchaoced53ae2016-11-29 15:00:51 +08003409bool ValidateDiscardFramebufferBase(Context *context,
3410 GLenum target,
3411 GLsizei numAttachments,
3412 const GLenum *attachments,
3413 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003414{
3415 if (numAttachments < 0)
3416 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003417 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003418 return false;
3419 }
3420
3421 for (GLsizei i = 0; i < numAttachments; ++i)
3422 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003423 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003424 {
3425 if (defaultFramebuffer)
3426 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003427 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003428 return false;
3429 }
3430
3431 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003433 context->handleError(InvalidOperation() << "Requested color attachment is "
3434 "greater than the maximum supported "
3435 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003436 return false;
3437 }
3438 }
3439 else
3440 {
3441 switch (attachments[i])
3442 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003443 case GL_DEPTH_ATTACHMENT:
3444 case GL_STENCIL_ATTACHMENT:
3445 case GL_DEPTH_STENCIL_ATTACHMENT:
3446 if (defaultFramebuffer)
3447 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003448 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3449 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003450 return false;
3451 }
3452 break;
3453 case GL_COLOR:
3454 case GL_DEPTH:
3455 case GL_STENCIL:
3456 if (!defaultFramebuffer)
3457 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003458 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3459 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003460 return false;
3461 }
3462 break;
3463 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003464 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003465 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003466 }
3467 }
3468 }
3469
3470 return true;
3471}
3472
Austin Kinross6ee1e782015-05-29 17:05:37 -07003473bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3474{
Jamie Madill007530e2017-12-28 14:27:04 -05003475 if (!context->getExtensions().debugMarker)
3476 {
3477 // The debug marker calls should not set error state
3478 // However, it seems reasonable to set an error state if the extension is not enabled
3479 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3480 return false;
3481 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003482
Jamie Madill007530e2017-12-28 14:27:04 -05003483 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003484 if (length < 0)
3485 {
3486 return false;
3487 }
3488
3489 if (marker == nullptr)
3490 {
3491 return false;
3492 }
3493
3494 return true;
3495}
3496
3497bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3498{
Jamie Madill007530e2017-12-28 14:27:04 -05003499 if (!context->getExtensions().debugMarker)
3500 {
3501 // The debug marker calls should not set error state
3502 // However, it seems reasonable to set an error state if the extension is not enabled
3503 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3504 return false;
3505 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003506
Jamie Madill007530e2017-12-28 14:27:04 -05003507 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003508 if (length < 0)
3509 {
3510 return false;
3511 }
3512
3513 if (length > 0 && marker == nullptr)
3514 {
3515 return false;
3516 }
3517
3518 return true;
3519}
3520
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003521bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003522{
Geoff Langa8406172015-07-21 16:53:39 -04003523 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003525 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003526 return false;
3527 }
3528
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003529 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003530 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003531 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003532 if (!context->getExtensions().eglImage)
3533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003534 context->handleError(InvalidEnum()
3535 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003536 }
3537 break;
3538
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003539 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003540 if (!context->getExtensions().eglImageExternal)
3541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003542 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3543 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003544 }
Geoff Langa8406172015-07-21 16:53:39 -04003545 break;
3546
3547 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003548 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003549 return false;
3550 }
3551
Jamie Madill007530e2017-12-28 14:27:04 -05003552 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3553
Jamie Madill61e16b42017-06-19 11:13:23 -04003554 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003555 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003557 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003558 return false;
3559 }
3560
Jamie Madill007530e2017-12-28 14:27:04 -05003561 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003563 context->handleError(InvalidOperation()
3564 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003565 return false;
3566 }
3567
Geoff Langca271392017-04-05 12:30:00 -04003568 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003569 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003570 if (!textureCaps.texturable)
3571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003572 context->handleError(InvalidOperation()
3573 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003574 return false;
3575 }
3576
Geoff Langdcab33b2015-07-21 13:03:16 -04003577 return true;
3578}
3579
3580bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003581 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003582 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003583{
Geoff Langa8406172015-07-21 16:53:39 -04003584 if (!context->getExtensions().eglImage)
3585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003586 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003587 return false;
3588 }
3589
3590 switch (target)
3591 {
3592 case GL_RENDERBUFFER:
3593 break;
3594
3595 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003596 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003597 return false;
3598 }
3599
Jamie Madill007530e2017-12-28 14:27:04 -05003600 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3601
Jamie Madill61e16b42017-06-19 11:13:23 -04003602 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003603 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003604 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003605 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003606 return false;
3607 }
3608
Geoff Langca271392017-04-05 12:30:00 -04003609 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003610 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003611 if (!textureCaps.renderable)
3612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003613 context->handleError(InvalidOperation()
3614 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003615 return false;
3616 }
3617
Geoff Langdcab33b2015-07-21 13:03:16 -04003618 return true;
3619}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003620
3621bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3622{
Geoff Lang36167ab2015-12-07 10:27:14 -05003623 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003624 {
3625 // The default VAO should always exist
3626 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003627 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003628 return false;
3629 }
3630
3631 return true;
3632}
3633
Geoff Langc5629752015-12-07 16:29:04 -05003634bool ValidateProgramBinaryBase(Context *context,
3635 GLuint program,
3636 GLenum binaryFormat,
3637 const void *binary,
3638 GLint length)
3639{
3640 Program *programObject = GetValidProgram(context, program);
3641 if (programObject == nullptr)
3642 {
3643 return false;
3644 }
3645
3646 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3647 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3648 programBinaryFormats.end())
3649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003650 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003651 return false;
3652 }
3653
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003654 if (context->hasActiveTransformFeedback(program))
3655 {
3656 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003657 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3658 "is associated with an active transform "
3659 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003660 return false;
3661 }
3662
Geoff Langc5629752015-12-07 16:29:04 -05003663 return true;
3664}
3665
3666bool ValidateGetProgramBinaryBase(Context *context,
3667 GLuint program,
3668 GLsizei bufSize,
3669 GLsizei *length,
3670 GLenum *binaryFormat,
3671 void *binary)
3672{
3673 Program *programObject = GetValidProgram(context, program);
3674 if (programObject == nullptr)
3675 {
3676 return false;
3677 }
3678
3679 if (!programObject->isLinked())
3680 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003681 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003682 return false;
3683 }
3684
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003685 if (context->getCaps().programBinaryFormats.empty())
3686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003687 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003688 return false;
3689 }
3690
Geoff Langc5629752015-12-07 16:29:04 -05003691 return true;
3692}
Jamie Madillc29968b2016-01-20 11:17:23 -05003693
Jamie Madill5b772312018-03-08 20:28:32 -05003694bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003695{
3696 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003697 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003698 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003699 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3700 return false;
3701 }
3702 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3703 {
3704 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003705 return false;
3706 }
3707
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003708 ASSERT(context->getGLState().getDrawFramebuffer());
3709 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003710 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3711
3712 // This should come first before the check for the default frame buffer
3713 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3714 // rather than INVALID_OPERATION
3715 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3716 {
3717 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3718
3719 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003720 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3721 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003722 {
3723 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003724 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3725 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3726 // 3.1 is still a bit ambiguous about the error, but future specs are
3727 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003729 return false;
3730 }
3731 else if (bufs[colorAttachment] >= maxColorAttachment)
3732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003733 context->handleError(InvalidOperation()
3734 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003735 return false;
3736 }
3737 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3738 frameBufferId != 0)
3739 {
3740 // INVALID_OPERATION-GL is bound to buffer and ith argument
3741 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003742 context->handleError(InvalidOperation()
3743 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003744 return false;
3745 }
3746 }
3747
3748 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3749 // and n is not 1 or bufs is bound to value other than BACK and NONE
3750 if (frameBufferId == 0)
3751 {
3752 if (n != 1)
3753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 context->handleError(InvalidOperation()
3755 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003756 return false;
3757 }
3758
3759 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003761 context->handleError(
3762 InvalidOperation()
3763 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003764 return false;
3765 }
3766 }
3767
3768 return true;
3769}
3770
Geoff Lang496c02d2016-10-20 11:38:11 -07003771bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003772 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003773 GLenum pname,
3774 GLsizei *length,
3775 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003776{
Geoff Lang496c02d2016-10-20 11:38:11 -07003777 if (length)
3778 {
3779 *length = 0;
3780 }
3781
3782 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3783 {
3784 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003785 InvalidOperation()
3786 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003787 return false;
3788 }
3789
Corentin Walleze4477002017-12-01 14:39:58 -05003790 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003791 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003792 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003793 return false;
3794 }
3795
Geoff Lang496c02d2016-10-20 11:38:11 -07003796 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003797 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003798 case GL_BUFFER_MAP_POINTER:
3799 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003800
Geoff Lang496c02d2016-10-20 11:38:11 -07003801 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003802 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003803 return false;
3804 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003805
3806 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3807 // target bound to zero generate an INVALID_OPERATION error."
3808 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003809 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003811 context->handleError(InvalidOperation()
3812 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003813 return false;
3814 }
3815
Geoff Lang496c02d2016-10-20 11:38:11 -07003816 if (length)
3817 {
3818 *length = 1;
3819 }
3820
Olli Etuaho4f667482016-03-30 15:56:35 +03003821 return true;
3822}
3823
Corentin Wallez336129f2017-10-17 15:55:40 -04003824bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003825{
Corentin Walleze4477002017-12-01 14:39:58 -05003826 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003827 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003828 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003829 return false;
3830 }
3831
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003832 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003833
3834 if (buffer == nullptr || !buffer->isMapped())
3835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003836 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003837 return false;
3838 }
3839
3840 return true;
3841}
3842
3843bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003844 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003845 GLintptr offset,
3846 GLsizeiptr length,
3847 GLbitfield access)
3848{
Corentin Walleze4477002017-12-01 14:39:58 -05003849 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003850 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003851 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003852 return false;
3853 }
3854
Brandon Jones6cad5662017-06-14 13:25:13 -07003855 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003857 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3858 return false;
3859 }
3860
3861 if (length < 0)
3862 {
3863 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003864 return false;
3865 }
3866
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003867 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003868
3869 if (!buffer)
3870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003871 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003872 return false;
3873 }
3874
3875 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003876 CheckedNumeric<size_t> checkedOffset(offset);
3877 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003878
Jamie Madille2e406c2016-06-02 13:04:10 -04003879 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003881 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 return false;
3883 }
3884
3885 // Check for invalid bits in the mask
3886 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3887 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3888 GL_MAP_UNSYNCHRONIZED_BIT;
3889
3890 if (access & ~(allAccessBits))
3891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003892 context->handleError(InvalidValue()
3893 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003894 return false;
3895 }
3896
3897 if (length == 0)
3898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003899 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 return false;
3901 }
3902
3903 if (buffer->isMapped())
3904 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003905 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003906 return false;
3907 }
3908
3909 // Check for invalid bit combinations
3910 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003912 context->handleError(InvalidOperation()
3913 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 return false;
3915 }
3916
3917 GLbitfield writeOnlyBits =
3918 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3919
3920 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003922 context->handleError(InvalidOperation()
3923 << "Invalid access bits when mapping buffer for reading: 0x"
3924 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003925 return false;
3926 }
3927
3928 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003930 context->handleError(
3931 InvalidOperation()
3932 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003933 return false;
3934 }
Geoff Lang79f71042017-08-14 16:43:43 -04003935
3936 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003937}
3938
3939bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003940 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003941 GLintptr offset,
3942 GLsizeiptr length)
3943{
Brandon Jones6cad5662017-06-14 13:25:13 -07003944 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003945 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003946 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3947 return false;
3948 }
3949
3950 if (length < 0)
3951 {
3952 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003953 return false;
3954 }
3955
Corentin Walleze4477002017-12-01 14:39:58 -05003956 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003957 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003958 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003959 return false;
3960 }
3961
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003962 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003963
3964 if (buffer == nullptr)
3965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003966 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003967 return false;
3968 }
3969
3970 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3971 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003972 context->handleError(InvalidOperation()
3973 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003974 return false;
3975 }
3976
3977 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003978 CheckedNumeric<size_t> checkedOffset(offset);
3979 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003980
Jamie Madille2e406c2016-06-02 13:04:10 -04003981 if (!checkedSize.IsValid() ||
3982 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003984 context->handleError(InvalidValue()
3985 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003986 return false;
3987 }
3988
3989 return true;
3990}
3991
Olli Etuaho41997e72016-03-10 13:38:39 +02003992bool ValidateGenOrDelete(Context *context, GLint n)
3993{
3994 if (n < 0)
3995 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003996 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003997 return false;
3998 }
3999 return true;
4000}
4001
Jamie Madill5b772312018-03-08 20:28:32 -05004002bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004003{
4004 if (!context->getExtensions().robustClientMemory)
4005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004006 context->handleError(InvalidOperation()
4007 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 return false;
4009 }
4010
4011 if (bufSize < 0)
4012 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004013 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004014 return false;
4015 }
4016
4017 return true;
4018}
4019
Jamie Madill5b772312018-03-08 20:28:32 -05004020bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004021{
4022 if (bufSize < numParams)
4023 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004024 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4025 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004026 return false;
4027 }
4028
4029 return true;
4030}
4031
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004032bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004033 GLenum target,
4034 GLenum attachment,
4035 GLenum pname,
4036 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004037{
Geoff Lange8afa902017-09-27 15:00:43 -04004038 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004040 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004041 return false;
4042 }
4043
4044 int clientVersion = context->getClientMajorVersion();
4045
4046 switch (pname)
4047 {
4048 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4049 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4050 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4051 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4052 break;
4053
Martin Radeve5285d22017-07-14 16:23:53 +03004054 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4055 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4056 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4057 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4058 if (clientVersion < 3 || !context->getExtensions().multiview)
4059 {
4060 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4061 return false;
4062 }
4063 break;
4064
Geoff Langff5b2d52016-09-07 11:32:23 -04004065 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4066 if (clientVersion < 3 && !context->getExtensions().sRGB)
4067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004068 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004069 return false;
4070 }
4071 break;
4072
4073 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4074 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4075 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4076 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4077 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4078 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4079 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4080 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4081 if (clientVersion < 3)
4082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004083 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004084 return false;
4085 }
4086 break;
4087
4088 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004089 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004090 return false;
4091 }
4092
4093 // Determine if the attachment is a valid enum
4094 switch (attachment)
4095 {
4096 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 case GL_DEPTH:
4098 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004099 if (clientVersion < 3)
4100 {
Geoff Langfa125c92017-10-24 13:01:46 -04004101 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004102 return false;
4103 }
4104 break;
4105
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004106 case GL_DEPTH_STENCIL_ATTACHMENT:
4107 if (clientVersion < 3 && !context->isWebGL1())
4108 {
4109 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4110 return false;
4111 }
4112 break;
4113
Geoff Langfa125c92017-10-24 13:01:46 -04004114 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004115 case GL_DEPTH_ATTACHMENT:
4116 case GL_STENCIL_ATTACHMENT:
4117 break;
4118
4119 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004120 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4121 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004122 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4123 {
Geoff Langfa125c92017-10-24 13:01:46 -04004124 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004125 return false;
4126 }
4127 break;
4128 }
4129
4130 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4131 ASSERT(framebuffer);
4132
4133 if (framebuffer->id() == 0)
4134 {
4135 if (clientVersion < 3)
4136 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004137 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004138 return false;
4139 }
4140
4141 switch (attachment)
4142 {
4143 case GL_BACK:
4144 case GL_DEPTH:
4145 case GL_STENCIL:
4146 break;
4147
4148 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004150 return false;
4151 }
4152 }
4153 else
4154 {
4155 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4156 {
4157 // Valid attachment query
4158 }
4159 else
4160 {
4161 switch (attachment)
4162 {
4163 case GL_DEPTH_ATTACHMENT:
4164 case GL_STENCIL_ATTACHMENT:
4165 break;
4166
4167 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004168 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004170 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004171 return false;
4172 }
4173 break;
4174
4175 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004176 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004177 return false;
4178 }
4179 }
4180 }
4181
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004182 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004183 if (attachmentObject)
4184 {
4185 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4186 attachmentObject->type() == GL_TEXTURE ||
4187 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4188
4189 switch (pname)
4190 {
4191 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4192 if (attachmentObject->type() != GL_RENDERBUFFER &&
4193 attachmentObject->type() != GL_TEXTURE)
4194 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004195 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004196 return false;
4197 }
4198 break;
4199
4200 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4201 if (attachmentObject->type() != GL_TEXTURE)
4202 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004203 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004204 return false;
4205 }
4206 break;
4207
4208 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4209 if (attachmentObject->type() != GL_TEXTURE)
4210 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004211 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004212 return false;
4213 }
4214 break;
4215
4216 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4217 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4218 {
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 break;
4223
4224 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4225 if (attachmentObject->type() != GL_TEXTURE)
4226 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004227 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004228 return false;
4229 }
4230 break;
4231
4232 default:
4233 break;
4234 }
4235 }
4236 else
4237 {
4238 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4239 // is NONE, then querying any other pname will generate INVALID_ENUM.
4240
4241 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4242 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4243 // INVALID_OPERATION for all other pnames
4244
4245 switch (pname)
4246 {
4247 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4248 break;
4249
4250 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4251 if (clientVersion < 3)
4252 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004253 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004254 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004255 return false;
4256 }
4257 break;
4258
4259 default:
4260 if (clientVersion < 3)
4261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004262 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004263 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004264 return false;
4265 }
4266 else
4267 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004268 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004269 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004270 return false;
4271 }
4272 }
4273 }
4274
Martin Radeve5285d22017-07-14 16:23:53 +03004275 if (numParams)
4276 {
4277 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4278 {
4279 // Only when the viewport offsets are queried we can have a varying number of output
4280 // parameters.
4281 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4282 *numParams = numViews * 2;
4283 }
4284 else
4285 {
4286 // For all other queries we can have only one output parameter.
4287 *numParams = 1;
4288 }
4289 }
4290
Geoff Langff5b2d52016-09-07 11:32:23 -04004291 return true;
4292}
4293
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004294bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004295 GLenum target,
4296 GLenum attachment,
4297 GLenum pname,
4298 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004299 GLsizei *length,
4300 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004301{
4302 if (!ValidateRobustEntryPoint(context, bufSize))
4303 {
4304 return false;
4305 }
4306
Brandon Jonesd1049182018-03-28 10:02:20 -07004307 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004308 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004309 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004310 {
4311 return false;
4312 }
4313
Brandon Jonesd1049182018-03-28 10:02:20 -07004314 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004315 {
4316 return false;
4317 }
4318
Brandon Jonesd1049182018-03-28 10:02:20 -07004319 SetRobustLengthParam(length, numParams);
4320
Geoff Langff5b2d52016-09-07 11:32:23 -04004321 return true;
4322}
4323
Jamie Madill5b772312018-03-08 20:28:32 -05004324bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004325 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004326 GLenum pname,
4327 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004328 GLsizei *length,
4329 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004330{
4331 if (!ValidateRobustEntryPoint(context, bufSize))
4332 {
4333 return false;
4334 }
4335
Brandon Jonesd1049182018-03-28 10:02:20 -07004336 GLsizei numParams = 0;
4337
4338 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004339 {
4340 return false;
4341 }
4342
Brandon Jonesd1049182018-03-28 10:02:20 -07004343 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004344 {
4345 return false;
4346 }
4347
Brandon Jonesd1049182018-03-28 10:02:20 -07004348 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004349 return true;
4350}
4351
Jamie Madill5b772312018-03-08 20:28:32 -05004352bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004353 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004354 GLenum pname,
4355 GLsizei bufSize,
4356 GLsizei *length,
4357 GLint64 *params)
4358{
Brandon Jonesd1049182018-03-28 10:02:20 -07004359 GLsizei numParams = 0;
4360
Geoff Langebebe1c2016-10-14 12:01:31 -04004361 if (!ValidateRobustEntryPoint(context, bufSize))
4362 {
4363 return false;
4364 }
4365
Brandon Jonesd1049182018-03-28 10:02:20 -07004366 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004367 {
4368 return false;
4369 }
4370
Brandon Jonesd1049182018-03-28 10:02:20 -07004371 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004372 {
4373 return false;
4374 }
4375
Brandon Jonesd1049182018-03-28 10:02:20 -07004376 SetRobustLengthParam(length, numParams);
4377
Geoff Langff5b2d52016-09-07 11:32:23 -04004378 return true;
4379}
4380
Jamie Madill5b772312018-03-08 20:28:32 -05004381bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004382{
4383 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004384 if (numParams)
4385 {
4386 *numParams = 1;
4387 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004388
4389 Program *programObject = GetValidProgram(context, program);
4390 if (!programObject)
4391 {
4392 return false;
4393 }
4394
4395 switch (pname)
4396 {
4397 case GL_DELETE_STATUS:
4398 case GL_LINK_STATUS:
4399 case GL_VALIDATE_STATUS:
4400 case GL_INFO_LOG_LENGTH:
4401 case GL_ATTACHED_SHADERS:
4402 case GL_ACTIVE_ATTRIBUTES:
4403 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4404 case GL_ACTIVE_UNIFORMS:
4405 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4406 break;
4407
4408 case GL_PROGRAM_BINARY_LENGTH:
4409 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004411 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4412 "requires GL_OES_get_program_binary or "
4413 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004414 return false;
4415 }
4416 break;
4417
4418 case GL_ACTIVE_UNIFORM_BLOCKS:
4419 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4420 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4421 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4422 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4423 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4424 if (context->getClientMajorVersion() < 3)
4425 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004426 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004427 return false;
4428 }
4429 break;
4430
Yunchao He61afff12017-03-14 15:34:03 +08004431 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004432 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004433 if (context->getClientVersion() < Version(3, 1))
4434 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004436 return false;
4437 }
4438 break;
4439
Jiawei Shao6ae51612018-02-23 14:03:25 +08004440 case GL_COMPUTE_WORK_GROUP_SIZE:
4441 if (context->getClientVersion() < Version(3, 1))
4442 {
4443 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4444 return false;
4445 }
4446
4447 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4448 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4449 // program which has not been linked successfully, or which does not contain objects to
4450 // form a compute shader.
4451 if (!programObject->isLinked())
4452 {
4453 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4454 return false;
4455 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004456 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004457 {
4458 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4459 return false;
4460 }
4461 break;
4462
Jiawei Shao447bfac2018-03-14 14:23:40 +08004463 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4464 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4465 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4466 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4467 if (!context->getExtensions().geometryShader)
4468 {
4469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4470 return false;
4471 }
4472
4473 // [EXT_geometry_shader] Chapter 7.12
4474 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4475 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4476 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4477 // successfully, or which does not contain objects to form a geometry shader.
4478 if (!programObject->isLinked())
4479 {
4480 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4481 return false;
4482 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004483 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004484 {
4485 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4486 return false;
4487 }
4488 break;
4489
Geoff Langff5b2d52016-09-07 11:32:23 -04004490 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004491 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004492 return false;
4493 }
4494
4495 return true;
4496}
4497
4498bool ValidateGetProgramivRobustANGLE(Context *context,
4499 GLuint program,
4500 GLenum pname,
4501 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004502 GLsizei *length,
4503 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004504{
4505 if (!ValidateRobustEntryPoint(context, bufSize))
4506 {
4507 return false;
4508 }
4509
Brandon Jonesd1049182018-03-28 10:02:20 -07004510 GLsizei numParams = 0;
4511
4512 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004513 {
4514 return false;
4515 }
4516
Brandon Jonesd1049182018-03-28 10:02:20 -07004517 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004518 {
4519 return false;
4520 }
4521
Brandon Jonesd1049182018-03-28 10:02:20 -07004522 SetRobustLengthParam(length, numParams);
4523
Geoff Langff5b2d52016-09-07 11:32:23 -04004524 return true;
4525}
4526
Geoff Lang740d9022016-10-07 11:20:52 -04004527bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4528 GLenum target,
4529 GLenum pname,
4530 GLsizei bufSize,
4531 GLsizei *length,
4532 GLint *params)
4533{
4534 if (!ValidateRobustEntryPoint(context, bufSize))
4535 {
4536 return false;
4537 }
4538
Brandon Jonesd1049182018-03-28 10:02:20 -07004539 GLsizei numParams = 0;
4540
4541 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004542 {
4543 return false;
4544 }
4545
Brandon Jonesd1049182018-03-28 10:02:20 -07004546 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004547 {
4548 return false;
4549 }
4550
Brandon Jonesd1049182018-03-28 10:02:20 -07004551 SetRobustLengthParam(length, numParams);
4552
Geoff Lang740d9022016-10-07 11:20:52 -04004553 return true;
4554}
4555
Geoff Langd7d0ed32016-10-07 11:33:51 -04004556bool ValidateGetShaderivRobustANGLE(Context *context,
4557 GLuint shader,
4558 GLenum pname,
4559 GLsizei bufSize,
4560 GLsizei *length,
4561 GLint *params)
4562{
4563 if (!ValidateRobustEntryPoint(context, bufSize))
4564 {
4565 return false;
4566 }
4567
Brandon Jonesd1049182018-03-28 10:02:20 -07004568 GLsizei numParams = 0;
4569
4570 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004571 {
4572 return false;
4573 }
4574
Brandon Jonesd1049182018-03-28 10:02:20 -07004575 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004576 {
4577 return false;
4578 }
4579
Brandon Jonesd1049182018-03-28 10:02:20 -07004580 SetRobustLengthParam(length, numParams);
4581
Geoff Langd7d0ed32016-10-07 11:33:51 -04004582 return true;
4583}
4584
Geoff Langc1984ed2016-10-07 12:41:00 -04004585bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004586 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004587 GLenum pname,
4588 GLsizei bufSize,
4589 GLsizei *length,
4590 GLfloat *params)
4591{
4592 if (!ValidateRobustEntryPoint(context, bufSize))
4593 {
4594 return false;
4595 }
4596
Brandon Jonesd1049182018-03-28 10:02:20 -07004597 GLsizei numParams = 0;
4598
4599 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004600 {
4601 return false;
4602 }
4603
Brandon Jonesd1049182018-03-28 10:02:20 -07004604 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004605 {
4606 return false;
4607 }
4608
Brandon Jonesd1049182018-03-28 10:02:20 -07004609 SetRobustLengthParam(length, numParams);
4610
Geoff Langc1984ed2016-10-07 12:41:00 -04004611 return true;
4612}
4613
Geoff Langc1984ed2016-10-07 12:41:00 -04004614bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004615 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004616 GLenum pname,
4617 GLsizei bufSize,
4618 GLsizei *length,
4619 GLint *params)
4620{
Brandon Jonesd1049182018-03-28 10:02:20 -07004621
Geoff Langc1984ed2016-10-07 12:41:00 -04004622 if (!ValidateRobustEntryPoint(context, bufSize))
4623 {
4624 return false;
4625 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004626 GLsizei numParams = 0;
4627 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004628 {
4629 return false;
4630 }
4631
Brandon Jonesd1049182018-03-28 10:02:20 -07004632 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004633 {
4634 return false;
4635 }
4636
Brandon Jonesd1049182018-03-28 10:02:20 -07004637 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004638 return true;
4639}
4640
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004641bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4642 TextureType target,
4643 GLenum pname,
4644 GLsizei bufSize,
4645 GLsizei *length,
4646 GLint *params)
4647{
4648 UNIMPLEMENTED();
4649 return false;
4650}
4651
4652bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4653 TextureType target,
4654 GLenum pname,
4655 GLsizei bufSize,
4656 GLsizei *length,
4657 GLuint *params)
4658{
4659 UNIMPLEMENTED();
4660 return false;
4661}
4662
Geoff Langc1984ed2016-10-07 12:41:00 -04004663bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004664 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004665 GLenum pname,
4666 GLsizei bufSize,
4667 const GLfloat *params)
4668{
4669 if (!ValidateRobustEntryPoint(context, bufSize))
4670 {
4671 return false;
4672 }
4673
4674 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4675}
4676
Geoff Langc1984ed2016-10-07 12:41:00 -04004677bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004678 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004679 GLenum pname,
4680 GLsizei bufSize,
4681 const GLint *params)
4682{
4683 if (!ValidateRobustEntryPoint(context, bufSize))
4684 {
4685 return false;
4686 }
4687
4688 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4689}
4690
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004691bool ValidateTexParameterIivRobustANGLE(Context *context,
4692 TextureType target,
4693 GLenum pname,
4694 GLsizei bufSize,
4695 const GLint *params)
4696{
4697 UNIMPLEMENTED();
4698 return false;
4699}
4700
4701bool ValidateTexParameterIuivRobustANGLE(Context *context,
4702 TextureType target,
4703 GLenum pname,
4704 GLsizei bufSize,
4705 const GLuint *params)
4706{
4707 UNIMPLEMENTED();
4708 return false;
4709}
4710
Geoff Langc1984ed2016-10-07 12:41:00 -04004711bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4712 GLuint sampler,
4713 GLenum pname,
4714 GLuint bufSize,
4715 GLsizei *length,
4716 GLfloat *params)
4717{
4718 if (!ValidateRobustEntryPoint(context, bufSize))
4719 {
4720 return false;
4721 }
4722
Brandon Jonesd1049182018-03-28 10:02:20 -07004723 GLsizei numParams = 0;
4724
4725 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004726 {
4727 return false;
4728 }
4729
Brandon Jonesd1049182018-03-28 10:02:20 -07004730 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004731 {
4732 return false;
4733 }
4734
Brandon Jonesd1049182018-03-28 10:02:20 -07004735 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004736 return true;
4737}
4738
Geoff Langc1984ed2016-10-07 12:41:00 -04004739bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4740 GLuint sampler,
4741 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004742 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004743 GLsizei *length,
4744 GLint *params)
4745{
4746 if (!ValidateRobustEntryPoint(context, bufSize))
4747 {
4748 return false;
4749 }
4750
Brandon Jonesd1049182018-03-28 10:02:20 -07004751 GLsizei numParams = 0;
4752
4753 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004754 {
4755 return false;
4756 }
4757
Brandon Jonesd1049182018-03-28 10:02:20 -07004758 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004759 {
4760 return false;
4761 }
4762
Brandon Jonesd1049182018-03-28 10:02:20 -07004763 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004764 return true;
4765}
4766
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004767bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4768 GLuint sampler,
4769 GLenum pname,
4770 GLsizei bufSize,
4771 GLsizei *length,
4772 GLint *params)
4773{
4774 UNIMPLEMENTED();
4775 return false;
4776}
4777
4778bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4779 GLuint sampler,
4780 GLenum pname,
4781 GLsizei bufSize,
4782 GLsizei *length,
4783 GLuint *params)
4784{
4785 UNIMPLEMENTED();
4786 return false;
4787}
4788
Geoff Langc1984ed2016-10-07 12:41:00 -04004789bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4790 GLuint sampler,
4791 GLenum pname,
4792 GLsizei bufSize,
4793 const GLfloat *params)
4794{
4795 if (!ValidateRobustEntryPoint(context, bufSize))
4796 {
4797 return false;
4798 }
4799
4800 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4801}
4802
Geoff Langc1984ed2016-10-07 12:41:00 -04004803bool ValidateSamplerParameterivRobustANGLE(Context *context,
4804 GLuint sampler,
4805 GLenum pname,
4806 GLsizei bufSize,
4807 const GLint *params)
4808{
4809 if (!ValidateRobustEntryPoint(context, bufSize))
4810 {
4811 return false;
4812 }
4813
4814 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4815}
4816
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004817bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4818 GLuint sampler,
4819 GLenum pname,
4820 GLsizei bufSize,
4821 const GLint *param)
4822{
4823 UNIMPLEMENTED();
4824 return false;
4825}
4826
4827bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4828 GLuint sampler,
4829 GLenum pname,
4830 GLsizei bufSize,
4831 const GLuint *param)
4832{
4833 UNIMPLEMENTED();
4834 return false;
4835}
4836
Geoff Lang0b031062016-10-13 14:30:04 -04004837bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4838 GLuint index,
4839 GLenum pname,
4840 GLsizei bufSize,
4841 GLsizei *length,
4842 GLfloat *params)
4843{
4844 if (!ValidateRobustEntryPoint(context, bufSize))
4845 {
4846 return false;
4847 }
4848
Brandon Jonesd1049182018-03-28 10:02:20 -07004849 GLsizei writeLength = 0;
4850
4851 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004852 {
4853 return false;
4854 }
4855
Brandon Jonesd1049182018-03-28 10:02:20 -07004856 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004857 {
4858 return false;
4859 }
4860
Brandon Jonesd1049182018-03-28 10:02:20 -07004861 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004862 return true;
4863}
4864
Geoff Lang0b031062016-10-13 14:30:04 -04004865bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4866 GLuint index,
4867 GLenum pname,
4868 GLsizei bufSize,
4869 GLsizei *length,
4870 GLint *params)
4871{
4872 if (!ValidateRobustEntryPoint(context, bufSize))
4873 {
4874 return false;
4875 }
4876
Brandon Jonesd1049182018-03-28 10:02:20 -07004877 GLsizei writeLength = 0;
4878
4879 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004880 {
4881 return false;
4882 }
4883
Brandon Jonesd1049182018-03-28 10:02:20 -07004884 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004885 {
4886 return false;
4887 }
4888
Brandon Jonesd1049182018-03-28 10:02:20 -07004889 SetRobustLengthParam(length, writeLength);
4890
Geoff Lang0b031062016-10-13 14:30:04 -04004891 return true;
4892}
4893
Geoff Lang0b031062016-10-13 14:30:04 -04004894bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4895 GLuint index,
4896 GLenum pname,
4897 GLsizei bufSize,
4898 GLsizei *length,
4899 void **pointer)
4900{
4901 if (!ValidateRobustEntryPoint(context, bufSize))
4902 {
4903 return false;
4904 }
4905
Brandon Jonesd1049182018-03-28 10:02:20 -07004906 GLsizei writeLength = 0;
4907
4908 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004909 {
4910 return false;
4911 }
4912
Brandon Jonesd1049182018-03-28 10:02:20 -07004913 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004914 {
4915 return false;
4916 }
4917
Brandon Jonesd1049182018-03-28 10:02:20 -07004918 SetRobustLengthParam(length, writeLength);
4919
Geoff Lang0b031062016-10-13 14:30:04 -04004920 return true;
4921}
4922
Geoff Lang0b031062016-10-13 14:30:04 -04004923bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4924 GLuint index,
4925 GLenum pname,
4926 GLsizei bufSize,
4927 GLsizei *length,
4928 GLint *params)
4929{
4930 if (!ValidateRobustEntryPoint(context, bufSize))
4931 {
4932 return false;
4933 }
4934
Brandon Jonesd1049182018-03-28 10:02:20 -07004935 GLsizei writeLength = 0;
4936
4937 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004938 {
4939 return false;
4940 }
4941
Brandon Jonesd1049182018-03-28 10:02:20 -07004942 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004943 {
4944 return false;
4945 }
4946
Brandon Jonesd1049182018-03-28 10:02:20 -07004947 SetRobustLengthParam(length, writeLength);
4948
Geoff Lang0b031062016-10-13 14:30:04 -04004949 return true;
4950}
4951
Geoff Lang0b031062016-10-13 14:30:04 -04004952bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4953 GLuint index,
4954 GLenum pname,
4955 GLsizei bufSize,
4956 GLsizei *length,
4957 GLuint *params)
4958{
4959 if (!ValidateRobustEntryPoint(context, bufSize))
4960 {
4961 return false;
4962 }
4963
Brandon Jonesd1049182018-03-28 10:02:20 -07004964 GLsizei writeLength = 0;
4965
4966 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004967 {
4968 return false;
4969 }
4970
Brandon Jonesd1049182018-03-28 10:02:20 -07004971 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004972 {
4973 return false;
4974 }
4975
Brandon Jonesd1049182018-03-28 10:02:20 -07004976 SetRobustLengthParam(length, writeLength);
4977
Geoff Lang0b031062016-10-13 14:30:04 -04004978 return true;
4979}
4980
Geoff Lang6899b872016-10-14 11:30:13 -04004981bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4982 GLuint program,
4983 GLuint uniformBlockIndex,
4984 GLenum pname,
4985 GLsizei bufSize,
4986 GLsizei *length,
4987 GLint *params)
4988{
4989 if (!ValidateRobustEntryPoint(context, bufSize))
4990 {
4991 return false;
4992 }
4993
Brandon Jonesd1049182018-03-28 10:02:20 -07004994 GLsizei writeLength = 0;
4995
4996 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4997 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004998 {
4999 return false;
5000 }
5001
Brandon Jonesd1049182018-03-28 10:02:20 -07005002 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005003 {
5004 return false;
5005 }
5006
Brandon Jonesd1049182018-03-28 10:02:20 -07005007 SetRobustLengthParam(length, writeLength);
5008
Geoff Lang6899b872016-10-14 11:30:13 -04005009 return true;
5010}
5011
Brandon Jones416aaf92018-04-10 08:10:16 -07005012bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005013 GLenum target,
5014 GLenum internalformat,
5015 GLenum pname,
5016 GLsizei bufSize,
5017 GLsizei *length,
5018 GLint *params)
5019{
5020 if (!ValidateRobustEntryPoint(context, bufSize))
5021 {
5022 return false;
5023 }
5024
Brandon Jonesd1049182018-03-28 10:02:20 -07005025 GLsizei numParams = 0;
5026
5027 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5028 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005029 {
5030 return false;
5031 }
5032
Brandon Jonesd1049182018-03-28 10:02:20 -07005033 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005034 {
5035 return false;
5036 }
5037
Brandon Jonesd1049182018-03-28 10:02:20 -07005038 SetRobustLengthParam(length, numParams);
5039
Geoff Lang0a9661f2016-10-20 10:59:20 -07005040 return true;
5041}
5042
Jamie Madill5b772312018-03-08 20:28:32 -05005043bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005044 GLuint attribIndex,
5045 GLint size,
5046 GLenum type,
5047 GLboolean pureInteger)
5048{
5049 const Caps &caps = context->getCaps();
5050 if (attribIndex >= caps.maxVertexAttributes)
5051 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005052 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005053 return false;
5054 }
5055
5056 if (size < 1 || size > 4)
5057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005058 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005059 return false;
Shao80957d92017-02-20 21:25:59 +08005060 }
5061
5062 switch (type)
5063 {
5064 case GL_BYTE:
5065 case GL_UNSIGNED_BYTE:
5066 case GL_SHORT:
5067 case GL_UNSIGNED_SHORT:
5068 break;
5069
5070 case GL_INT:
5071 case GL_UNSIGNED_INT:
5072 if (context->getClientMajorVersion() < 3)
5073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005074 context->handleError(InvalidEnum()
5075 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005076 return false;
5077 }
5078 break;
5079
5080 case GL_FIXED:
5081 case GL_FLOAT:
5082 if (pureInteger)
5083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005084 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005085 return false;
5086 }
5087 break;
5088
5089 case GL_HALF_FLOAT:
5090 if (context->getClientMajorVersion() < 3)
5091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005092 context->handleError(InvalidEnum()
5093 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005094 return false;
5095 }
5096 if (pureInteger)
5097 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005098 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005099 return false;
5100 }
5101 break;
5102
5103 case GL_INT_2_10_10_10_REV:
5104 case GL_UNSIGNED_INT_2_10_10_10_REV:
5105 if (context->getClientMajorVersion() < 3)
5106 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005107 context->handleError(InvalidEnum()
5108 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005109 return false;
5110 }
5111 if (pureInteger)
5112 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005113 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005114 return false;
5115 }
5116 if (size != 4)
5117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005118 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5119 "UNSIGNED_INT_2_10_10_10_REV and "
5120 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005121 return false;
5122 }
5123 break;
5124
5125 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005126 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005127 return false;
5128 }
5129
5130 return true;
5131}
5132
Geoff Lang76e65652017-03-27 14:58:02 -04005133// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5134// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5135// specified clear value and the type of a buffer that is being cleared generates an
5136// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005137bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005138 GLint drawbuffer,
5139 const GLenum *validComponentTypes,
5140 size_t validComponentTypeCount)
5141{
5142 const FramebufferAttachment *attachment =
5143 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5144 if (attachment)
5145 {
5146 GLenum componentType = attachment->getFormat().info->componentType;
5147 const GLenum *end = validComponentTypes + validComponentTypeCount;
5148 if (std::find(validComponentTypes, end, componentType) == end)
5149 {
5150 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005151 InvalidOperation()
5152 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005153 return false;
5154 }
5155 }
5156
5157 return true;
5158}
5159
Jamie Madill5b772312018-03-08 20:28:32 -05005160bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005161{
5162 if (!ValidateRobustEntryPoint(context, dataSize))
5163 {
5164 return false;
5165 }
5166
Corentin Wallez336129f2017-10-17 15:55:40 -04005167 gl::Buffer *pixelUnpackBuffer =
5168 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005169 if (pixelUnpackBuffer == nullptr)
5170 {
5171 if (dataSize < imageSize)
5172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005173 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005174 }
5175 }
5176 return true;
5177}
5178
Jamie Madill5b772312018-03-08 20:28:32 -05005179bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005180 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005181 GLenum pname,
5182 bool pointerVersion,
5183 GLsizei *numParams)
5184{
5185 if (numParams)
5186 {
5187 *numParams = 0;
5188 }
5189
Corentin Walleze4477002017-12-01 14:39:58 -05005190 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005193 return false;
5194 }
5195
5196 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5197 if (!buffer)
5198 {
5199 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005201 return false;
5202 }
5203
5204 const Extensions &extensions = context->getExtensions();
5205
5206 switch (pname)
5207 {
5208 case GL_BUFFER_USAGE:
5209 case GL_BUFFER_SIZE:
5210 break;
5211
5212 case GL_BUFFER_ACCESS_OES:
5213 if (!extensions.mapBuffer)
5214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005215 context->handleError(InvalidEnum()
5216 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005217 return false;
5218 }
5219 break;
5220
5221 case GL_BUFFER_MAPPED:
5222 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5223 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5224 !extensions.mapBufferRange)
5225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005226 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5227 "GL_OES_mapbuffer or "
5228 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005229 return false;
5230 }
5231 break;
5232
5233 case GL_BUFFER_MAP_POINTER:
5234 if (!pointerVersion)
5235 {
5236 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005237 InvalidEnum()
5238 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005239 return false;
5240 }
5241 break;
5242
5243 case GL_BUFFER_ACCESS_FLAGS:
5244 case GL_BUFFER_MAP_OFFSET:
5245 case GL_BUFFER_MAP_LENGTH:
5246 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005248 context->handleError(InvalidEnum()
5249 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005250 return false;
5251 }
5252 break;
5253
5254 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005256 return false;
5257 }
5258
5259 // All buffer parameter queries return one value.
5260 if (numParams)
5261 {
5262 *numParams = 1;
5263 }
5264
5265 return true;
5266}
5267
5268bool ValidateGetRenderbufferParameterivBase(Context *context,
5269 GLenum target,
5270 GLenum pname,
5271 GLsizei *length)
5272{
5273 if (length)
5274 {
5275 *length = 0;
5276 }
5277
5278 if (target != GL_RENDERBUFFER)
5279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005280 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005281 return false;
5282 }
5283
5284 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5285 if (renderbuffer == nullptr)
5286 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005287 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005288 return false;
5289 }
5290
5291 switch (pname)
5292 {
5293 case GL_RENDERBUFFER_WIDTH:
5294 case GL_RENDERBUFFER_HEIGHT:
5295 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5296 case GL_RENDERBUFFER_RED_SIZE:
5297 case GL_RENDERBUFFER_GREEN_SIZE:
5298 case GL_RENDERBUFFER_BLUE_SIZE:
5299 case GL_RENDERBUFFER_ALPHA_SIZE:
5300 case GL_RENDERBUFFER_DEPTH_SIZE:
5301 case GL_RENDERBUFFER_STENCIL_SIZE:
5302 break;
5303
5304 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5305 if (!context->getExtensions().framebufferMultisample)
5306 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005308 return false;
5309 }
5310 break;
5311
5312 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005313 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005314 return false;
5315 }
5316
5317 if (length)
5318 {
5319 *length = 1;
5320 }
5321 return true;
5322}
5323
5324bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5325{
5326 if (length)
5327 {
5328 *length = 0;
5329 }
5330
5331 if (GetValidShader(context, shader) == nullptr)
5332 {
5333 return false;
5334 }
5335
5336 switch (pname)
5337 {
5338 case GL_SHADER_TYPE:
5339 case GL_DELETE_STATUS:
5340 case GL_COMPILE_STATUS:
5341 case GL_INFO_LOG_LENGTH:
5342 case GL_SHADER_SOURCE_LENGTH:
5343 break;
5344
5345 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5346 if (!context->getExtensions().translatedShaderSource)
5347 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005348 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005349 return false;
5350 }
5351 break;
5352
5353 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005355 return false;
5356 }
5357
5358 if (length)
5359 {
5360 *length = 1;
5361 }
5362 return true;
5363}
5364
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005365bool ValidateGetTexParameterBase(Context *context,
5366 TextureType target,
5367 GLenum pname,
5368 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005369{
5370 if (length)
5371 {
5372 *length = 0;
5373 }
5374
5375 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5376 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 return false;
5379 }
5380
5381 if (context->getTargetTexture(target) == nullptr)
5382 {
5383 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005384 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005385 return false;
5386 }
5387
5388 switch (pname)
5389 {
5390 case GL_TEXTURE_MAG_FILTER:
5391 case GL_TEXTURE_MIN_FILTER:
5392 case GL_TEXTURE_WRAP_S:
5393 case GL_TEXTURE_WRAP_T:
5394 break;
5395
5396 case GL_TEXTURE_USAGE_ANGLE:
5397 if (!context->getExtensions().textureUsage)
5398 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005399 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005400 return false;
5401 }
5402 break;
5403
5404 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005405 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005406 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005407 return false;
5408 }
5409 break;
5410
5411 case GL_TEXTURE_IMMUTABLE_FORMAT:
5412 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5413 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005414 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005415 return false;
5416 }
5417 break;
5418
5419 case GL_TEXTURE_WRAP_R:
5420 case GL_TEXTURE_IMMUTABLE_LEVELS:
5421 case GL_TEXTURE_SWIZZLE_R:
5422 case GL_TEXTURE_SWIZZLE_G:
5423 case GL_TEXTURE_SWIZZLE_B:
5424 case GL_TEXTURE_SWIZZLE_A:
5425 case GL_TEXTURE_BASE_LEVEL:
5426 case GL_TEXTURE_MAX_LEVEL:
5427 case GL_TEXTURE_MIN_LOD:
5428 case GL_TEXTURE_MAX_LOD:
5429 case GL_TEXTURE_COMPARE_MODE:
5430 case GL_TEXTURE_COMPARE_FUNC:
5431 if (context->getClientMajorVersion() < 3)
5432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005433 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005434 return false;
5435 }
5436 break;
5437
5438 case GL_TEXTURE_SRGB_DECODE_EXT:
5439 if (!context->getExtensions().textureSRGBDecode)
5440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005441 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005442 return false;
5443 }
5444 break;
5445
Yunchao Hebacaa712018-01-30 14:01:39 +08005446 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5447 if (context->getClientVersion() < Version(3, 1))
5448 {
5449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5450 return false;
5451 }
5452 break;
5453
Jamie Madillbe849e42017-05-02 15:49:00 -04005454 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005455 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005456 return false;
5457 }
5458
5459 if (length)
5460 {
5461 *length = 1;
5462 }
5463 return true;
5464}
5465
5466bool ValidateGetVertexAttribBase(Context *context,
5467 GLuint index,
5468 GLenum pname,
5469 GLsizei *length,
5470 bool pointer,
5471 bool pureIntegerEntryPoint)
5472{
5473 if (length)
5474 {
5475 *length = 0;
5476 }
5477
5478 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005480 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 return false;
5482 }
5483
5484 if (index >= context->getCaps().maxVertexAttributes)
5485 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005486 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005487 return false;
5488 }
5489
5490 if (pointer)
5491 {
5492 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5493 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005494 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005495 return false;
5496 }
5497 }
5498 else
5499 {
5500 switch (pname)
5501 {
5502 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5503 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5504 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5505 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5506 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5507 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5508 case GL_CURRENT_VERTEX_ATTRIB:
5509 break;
5510
5511 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5512 static_assert(
5513 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5514 "ANGLE extension enums not equal to GL enums.");
5515 if (context->getClientMajorVersion() < 3 &&
5516 !context->getExtensions().instancedArrays)
5517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005518 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5519 "requires OpenGL ES 3.0 or "
5520 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005521 return false;
5522 }
5523 break;
5524
5525 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5526 if (context->getClientMajorVersion() < 3)
5527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005528 context->handleError(
5529 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005530 return false;
5531 }
5532 break;
5533
5534 case GL_VERTEX_ATTRIB_BINDING:
5535 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5536 if (context->getClientVersion() < ES_3_1)
5537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005538 context->handleError(InvalidEnum()
5539 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005540 return false;
5541 }
5542 break;
5543
5544 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005545 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005546 return false;
5547 }
5548 }
5549
5550 if (length)
5551 {
5552 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5553 {
5554 *length = 4;
5555 }
5556 else
5557 {
5558 *length = 1;
5559 }
5560 }
5561
5562 return true;
5563}
5564
Jamie Madill4928b7c2017-06-20 12:57:39 -04005565bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 GLint x,
5567 GLint y,
5568 GLsizei width,
5569 GLsizei height,
5570 GLenum format,
5571 GLenum type,
5572 GLsizei bufSize,
5573 GLsizei *length,
5574 GLsizei *columns,
5575 GLsizei *rows,
5576 void *pixels)
5577{
5578 if (length != nullptr)
5579 {
5580 *length = 0;
5581 }
5582 if (rows != nullptr)
5583 {
5584 *rows = 0;
5585 }
5586 if (columns != nullptr)
5587 {
5588 *columns = 0;
5589 }
5590
5591 if (width < 0 || height < 0)
5592 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005593 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005594 return false;
5595 }
5596
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005597 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005598
Jamie Madill427064d2018-04-13 16:20:34 -04005599 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005600 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005601 return false;
5602 }
5603
Jamie Madille98b1b52018-03-08 09:47:23 -05005604 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005605 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005606 return false;
5607 }
5608
Jamie Madill690c8eb2018-03-12 15:20:03 -04005609 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005610 ASSERT(framebuffer);
5611
5612 if (framebuffer->getReadBufferState() == GL_NONE)
5613 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005614 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005615 return false;
5616 }
5617
5618 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5619 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5620 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5621 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5622 // situation is an application error that would lead to a crash in ANGLE.
5623 if (readBuffer == nullptr)
5624 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005625 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005626 return false;
5627 }
5628
Martin Radev28031682017-07-28 14:47:56 +03005629 // ANGLE_multiview, Revision 1:
5630 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5631 // current read framebuffer is not NONE.
5632 if (readBuffer->getMultiviewLayout() != GL_NONE)
5633 {
5634 context->handleError(InvalidFramebufferOperation()
5635 << "Attempting to read from a multi-view framebuffer.");
5636 return false;
5637 }
5638
Geoff Lang280ba992017-04-18 16:30:58 -04005639 if (context->getExtensions().webglCompatibility)
5640 {
5641 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5642 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5643 // and type before validating the combination of format and type. However, the
5644 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5645 // verifies that GL_INVALID_OPERATION is generated.
5646 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5647 // dEQP/WebGL.
5648 if (!ValidReadPixelsFormatEnum(context, format))
5649 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005650 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005651 return false;
5652 }
5653
5654 if (!ValidReadPixelsTypeEnum(context, type))
5655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005656 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005657 return false;
5658 }
5659 }
5660
Jamie Madill690c8eb2018-03-12 15:20:03 -04005661 GLenum currentFormat = GL_NONE;
5662 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5663
5664 GLenum currentType = GL_NONE;
5665 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5666
Jamie Madillbe849e42017-05-02 15:49:00 -04005667 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5668
5669 bool validFormatTypeCombination =
5670 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5671
5672 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5673 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005675 return false;
5676 }
5677
5678 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005679 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005680 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5681 {
5682 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005683 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005684 return false;
5685 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005686 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5687 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5688 {
5689 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5690 return false;
5691 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005692
5693 // .. the data would be packed to the buffer object such that the memory writes required
5694 // would exceed the data store size.
5695 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5696 const gl::Extents size(width, height, 1);
5697 const auto &pack = context->getGLState().getPackState();
5698
5699 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5700 if (endByteOrErr.isError())
5701 {
5702 context->handleError(endByteOrErr.getError());
5703 return false;
5704 }
5705
5706 size_t endByte = endByteOrErr.getResult();
5707 if (bufSize >= 0)
5708 {
5709 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5710 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005711 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005712 return false;
5713 }
5714 }
5715
5716 if (pixelPackBuffer != nullptr)
5717 {
5718 CheckedNumeric<size_t> checkedEndByte(endByte);
5719 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5720 checkedEndByte += checkedOffset;
5721
5722 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5723 {
5724 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005725 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005726 return false;
5727 }
5728 }
5729
5730 if (pixelPackBuffer == nullptr && length != nullptr)
5731 {
5732 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5733 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005734 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005735 return false;
5736 }
5737
5738 *length = static_cast<GLsizei>(endByte);
5739 }
5740
Geoff Langa953b522018-02-21 16:56:23 -05005741 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005742 angle::CheckedNumeric<int> clippedExtent(length);
5743 if (start < 0)
5744 {
5745 // "subtract" the area that is less than 0
5746 clippedExtent += start;
5747 }
5748
Geoff Langa953b522018-02-21 16:56:23 -05005749 angle::CheckedNumeric<int> readExtent = start;
5750 readExtent += length;
5751 if (!readExtent.IsValid())
5752 {
5753 return false;
5754 }
5755
5756 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005757 {
5758 // Subtract the region to the right of the read buffer
5759 clippedExtent -= (readExtent - bufferSize);
5760 }
5761
5762 if (!clippedExtent.IsValid())
5763 {
Geoff Langa953b522018-02-21 16:56:23 -05005764 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005765 }
5766
Geoff Langa953b522018-02-21 16:56:23 -05005767 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5768 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005769 };
5770
Geoff Langa953b522018-02-21 16:56:23 -05005771 GLsizei writtenColumns = 0;
5772 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5773 {
5774 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5775 return false;
5776 }
5777
5778 GLsizei writtenRows = 0;
5779 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5780 {
5781 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5782 return false;
5783 }
5784
Jamie Madillbe849e42017-05-02 15:49:00 -04005785 if (columns != nullptr)
5786 {
Geoff Langa953b522018-02-21 16:56:23 -05005787 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005788 }
5789
5790 if (rows != nullptr)
5791 {
Geoff Langa953b522018-02-21 16:56:23 -05005792 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005793 }
5794
5795 return true;
5796}
5797
5798template <typename ParamType>
5799bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005800 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 GLenum pname,
5802 GLsizei bufSize,
5803 const ParamType *params)
5804{
5805 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5806 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005807 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005808 return false;
5809 }
5810
5811 if (context->getTargetTexture(target) == nullptr)
5812 {
5813 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005814 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 return false;
5816 }
5817
5818 const GLsizei minBufSize = 1;
5819 if (bufSize >= 0 && bufSize < minBufSize)
5820 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005821 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005822 return false;
5823 }
5824
5825 switch (pname)
5826 {
5827 case GL_TEXTURE_WRAP_R:
5828 case GL_TEXTURE_SWIZZLE_R:
5829 case GL_TEXTURE_SWIZZLE_G:
5830 case GL_TEXTURE_SWIZZLE_B:
5831 case GL_TEXTURE_SWIZZLE_A:
5832 case GL_TEXTURE_BASE_LEVEL:
5833 case GL_TEXTURE_MAX_LEVEL:
5834 case GL_TEXTURE_COMPARE_MODE:
5835 case GL_TEXTURE_COMPARE_FUNC:
5836 case GL_TEXTURE_MIN_LOD:
5837 case GL_TEXTURE_MAX_LOD:
5838 if (context->getClientMajorVersion() < 3)
5839 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005840 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005841 return false;
5842 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005843 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005844 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005845 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5846 "available without "
5847 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005848 return false;
5849 }
5850 break;
5851
5852 default:
5853 break;
5854 }
5855
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005856 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005857 {
5858 switch (pname)
5859 {
5860 case GL_TEXTURE_MIN_FILTER:
5861 case GL_TEXTURE_MAG_FILTER:
5862 case GL_TEXTURE_WRAP_S:
5863 case GL_TEXTURE_WRAP_T:
5864 case GL_TEXTURE_WRAP_R:
5865 case GL_TEXTURE_MIN_LOD:
5866 case GL_TEXTURE_MAX_LOD:
5867 case GL_TEXTURE_COMPARE_MODE:
5868 case GL_TEXTURE_COMPARE_FUNC:
5869 context->handleError(InvalidEnum()
5870 << "Invalid parameter for 2D multisampled textures.");
5871 return false;
5872 }
5873 }
5874
Jamie Madillbe849e42017-05-02 15:49:00 -04005875 switch (pname)
5876 {
5877 case GL_TEXTURE_WRAP_S:
5878 case GL_TEXTURE_WRAP_T:
5879 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005880 {
5881 bool restrictedWrapModes =
5882 target == TextureType::External || target == TextureType::Rectangle;
5883 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005884 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005885 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005886 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005887 }
5888 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005889
5890 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005891 {
5892 bool restrictedMinFilter =
5893 target == TextureType::External || target == TextureType::Rectangle;
5894 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005895 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005896 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005897 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005898 }
5899 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005900
5901 case GL_TEXTURE_MAG_FILTER:
5902 if (!ValidateTextureMagFilterValue(context, params))
5903 {
5904 return false;
5905 }
5906 break;
5907
5908 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005909 if (!context->getExtensions().textureUsage)
5910 {
5911 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5912 return false;
5913 }
5914
Jamie Madillbe849e42017-05-02 15:49:00 -04005915 switch (ConvertToGLenum(params[0]))
5916 {
5917 case GL_NONE:
5918 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5919 break;
5920
5921 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005922 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005923 return false;
5924 }
5925 break;
5926
5927 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005928 {
5929 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5930 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005931 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005932 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005933 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005934 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5935 }
5936 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005937
5938 case GL_TEXTURE_MIN_LOD:
5939 case GL_TEXTURE_MAX_LOD:
5940 // any value is permissible
5941 break;
5942
5943 case GL_TEXTURE_COMPARE_MODE:
5944 if (!ValidateTextureCompareModeValue(context, params))
5945 {
5946 return false;
5947 }
5948 break;
5949
5950 case GL_TEXTURE_COMPARE_FUNC:
5951 if (!ValidateTextureCompareFuncValue(context, params))
5952 {
5953 return false;
5954 }
5955 break;
5956
5957 case GL_TEXTURE_SWIZZLE_R:
5958 case GL_TEXTURE_SWIZZLE_G:
5959 case GL_TEXTURE_SWIZZLE_B:
5960 case GL_TEXTURE_SWIZZLE_A:
5961 switch (ConvertToGLenum(params[0]))
5962 {
5963 case GL_RED:
5964 case GL_GREEN:
5965 case GL_BLUE:
5966 case GL_ALPHA:
5967 case GL_ZERO:
5968 case GL_ONE:
5969 break;
5970
5971 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005972 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005973 return false;
5974 }
5975 break;
5976
5977 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005978 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005980 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005981 return false;
5982 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005983 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005984 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005985 context->handleError(InvalidOperation()
5986 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005987 return false;
5988 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005989 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005990 {
5991 context->handleError(InvalidOperation()
5992 << "Base level must be 0 for multisampled textures.");
5993 return false;
5994 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005995 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005996 {
5997 context->handleError(InvalidOperation()
5998 << "Base level must be 0 for rectangle textures.");
5999 return false;
6000 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006001 break;
6002
6003 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006004 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006006 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006007 return false;
6008 }
6009 break;
6010
6011 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6012 if (context->getClientVersion() < Version(3, 1))
6013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006015 return false;
6016 }
6017 switch (ConvertToGLenum(params[0]))
6018 {
6019 case GL_DEPTH_COMPONENT:
6020 case GL_STENCIL_INDEX:
6021 break;
6022
6023 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006024 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006025 return false;
6026 }
6027 break;
6028
6029 case GL_TEXTURE_SRGB_DECODE_EXT:
6030 if (!ValidateTextureSRGBDecodeValue(context, params))
6031 {
6032 return false;
6033 }
6034 break;
6035
6036 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006037 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006038 return false;
6039 }
6040
6041 return true;
6042}
6043
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006044template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6045template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006046
Jamie Madill5b772312018-03-08 20:28:32 -05006047bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006048{
6049 if (index >= MAX_VERTEX_ATTRIBS)
6050 {
6051 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6052 return false;
6053 }
6054
6055 return true;
6056}
6057
6058bool ValidateGetActiveUniformBlockivBase(Context *context,
6059 GLuint program,
6060 GLuint uniformBlockIndex,
6061 GLenum pname,
6062 GLsizei *length)
6063{
6064 if (length)
6065 {
6066 *length = 0;
6067 }
6068
6069 if (context->getClientMajorVersion() < 3)
6070 {
6071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6072 return false;
6073 }
6074
6075 Program *programObject = GetValidProgram(context, program);
6076 if (!programObject)
6077 {
6078 return false;
6079 }
6080
6081 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6082 {
6083 context->handleError(InvalidValue()
6084 << "uniformBlockIndex exceeds active uniform block count.");
6085 return false;
6086 }
6087
6088 switch (pname)
6089 {
6090 case GL_UNIFORM_BLOCK_BINDING:
6091 case GL_UNIFORM_BLOCK_DATA_SIZE:
6092 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6093 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6094 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6095 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6096 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6097 break;
6098
6099 default:
6100 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6101 return false;
6102 }
6103
6104 if (length)
6105 {
6106 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6107 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006108 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006109 programObject->getUniformBlockByIndex(uniformBlockIndex);
6110 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6111 }
6112 else
6113 {
6114 *length = 1;
6115 }
6116 }
6117
6118 return true;
6119}
6120
Jamie Madill9696d072017-08-26 23:19:57 -04006121template <typename ParamType>
6122bool ValidateSamplerParameterBase(Context *context,
6123 GLuint sampler,
6124 GLenum pname,
6125 GLsizei bufSize,
6126 ParamType *params)
6127{
6128 if (context->getClientMajorVersion() < 3)
6129 {
6130 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6131 return false;
6132 }
6133
6134 if (!context->isSampler(sampler))
6135 {
6136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6137 return false;
6138 }
6139
6140 const GLsizei minBufSize = 1;
6141 if (bufSize >= 0 && bufSize < minBufSize)
6142 {
6143 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6144 return false;
6145 }
6146
6147 switch (pname)
6148 {
6149 case GL_TEXTURE_WRAP_S:
6150 case GL_TEXTURE_WRAP_T:
6151 case GL_TEXTURE_WRAP_R:
6152 if (!ValidateTextureWrapModeValue(context, params, false))
6153 {
6154 return false;
6155 }
6156 break;
6157
6158 case GL_TEXTURE_MIN_FILTER:
6159 if (!ValidateTextureMinFilterValue(context, params, false))
6160 {
6161 return false;
6162 }
6163 break;
6164
6165 case GL_TEXTURE_MAG_FILTER:
6166 if (!ValidateTextureMagFilterValue(context, params))
6167 {
6168 return false;
6169 }
6170 break;
6171
6172 case GL_TEXTURE_MIN_LOD:
6173 case GL_TEXTURE_MAX_LOD:
6174 // any value is permissible
6175 break;
6176
6177 case GL_TEXTURE_COMPARE_MODE:
6178 if (!ValidateTextureCompareModeValue(context, params))
6179 {
6180 return false;
6181 }
6182 break;
6183
6184 case GL_TEXTURE_COMPARE_FUNC:
6185 if (!ValidateTextureCompareFuncValue(context, params))
6186 {
6187 return false;
6188 }
6189 break;
6190
6191 case GL_TEXTURE_SRGB_DECODE_EXT:
6192 if (!ValidateTextureSRGBDecodeValue(context, params))
6193 {
6194 return false;
6195 }
6196 break;
6197
Luc Ferron1b1a8642018-01-23 15:12:01 -05006198 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6199 {
6200 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6201 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6202 {
6203 return false;
6204 }
6205 }
6206 break;
6207
Jamie Madill9696d072017-08-26 23:19:57 -04006208 default:
6209 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6210 return false;
6211 }
6212
6213 return true;
6214}
6215
6216template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6217template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6218
6219bool ValidateGetSamplerParameterBase(Context *context,
6220 GLuint sampler,
6221 GLenum pname,
6222 GLsizei *length)
6223{
6224 if (length)
6225 {
6226 *length = 0;
6227 }
6228
6229 if (context->getClientMajorVersion() < 3)
6230 {
6231 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6232 return false;
6233 }
6234
6235 if (!context->isSampler(sampler))
6236 {
6237 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6238 return false;
6239 }
6240
6241 switch (pname)
6242 {
6243 case GL_TEXTURE_WRAP_S:
6244 case GL_TEXTURE_WRAP_T:
6245 case GL_TEXTURE_WRAP_R:
6246 case GL_TEXTURE_MIN_FILTER:
6247 case GL_TEXTURE_MAG_FILTER:
6248 case GL_TEXTURE_MIN_LOD:
6249 case GL_TEXTURE_MAX_LOD:
6250 case GL_TEXTURE_COMPARE_MODE:
6251 case GL_TEXTURE_COMPARE_FUNC:
6252 break;
6253
Luc Ferron1b1a8642018-01-23 15:12:01 -05006254 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6255 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6256 {
6257 return false;
6258 }
6259 break;
6260
Jamie Madill9696d072017-08-26 23:19:57 -04006261 case GL_TEXTURE_SRGB_DECODE_EXT:
6262 if (!context->getExtensions().textureSRGBDecode)
6263 {
6264 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6265 return false;
6266 }
6267 break;
6268
6269 default:
6270 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6271 return false;
6272 }
6273
6274 if (length)
6275 {
6276 *length = 1;
6277 }
6278 return true;
6279}
6280
6281bool ValidateGetInternalFormativBase(Context *context,
6282 GLenum target,
6283 GLenum internalformat,
6284 GLenum pname,
6285 GLsizei bufSize,
6286 GLsizei *numParams)
6287{
6288 if (numParams)
6289 {
6290 *numParams = 0;
6291 }
6292
6293 if (context->getClientMajorVersion() < 3)
6294 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006296 return false;
6297 }
6298
6299 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6300 if (!formatCaps.renderable)
6301 {
6302 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6303 return false;
6304 }
6305
6306 switch (target)
6307 {
6308 case GL_RENDERBUFFER:
6309 break;
6310
6311 case GL_TEXTURE_2D_MULTISAMPLE:
6312 if (context->getClientVersion() < ES_3_1)
6313 {
6314 context->handleError(InvalidOperation()
6315 << "Texture target requires at least OpenGL ES 3.1.");
6316 return false;
6317 }
6318 break;
6319
6320 default:
6321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6322 return false;
6323 }
6324
6325 if (bufSize < 0)
6326 {
6327 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6328 return false;
6329 }
6330
6331 GLsizei maxWriteParams = 0;
6332 switch (pname)
6333 {
6334 case GL_NUM_SAMPLE_COUNTS:
6335 maxWriteParams = 1;
6336 break;
6337
6338 case GL_SAMPLES:
6339 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6340 break;
6341
6342 default:
6343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6344 return false;
6345 }
6346
6347 if (numParams)
6348 {
6349 // glGetInternalFormativ will not overflow bufSize
6350 *numParams = std::min(bufSize, maxWriteParams);
6351 }
6352
6353 return true;
6354}
6355
Jamie Madille98b1b52018-03-08 09:47:23 -05006356bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6357{
Jamie Madill427064d2018-04-13 16:20:34 -04006358 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006359 {
6360 context->handleError(InvalidOperation());
6361 return false;
6362 }
6363 return true;
6364}
6365
Lingfeng Yang038dd532018-03-29 17:31:52 -07006366bool ValidateMultitextureUnit(Context *context, GLenum texture)
6367{
6368 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6369 {
6370 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6371 return false;
6372 }
6373 return true;
6374}
6375
Jamie Madillc29968b2016-01-20 11:17:23 -05006376} // namespace gl