blob: 486b336a6d294cc91157e3636cc22931ae711a63 [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}
Jamie Madill5b772312018-03-08 20:28:32 -050071bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040072{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070073 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040074 const gl::Program *program = state.getProgram();
75
Corentin Wallez327411e2016-12-09 11:09:17 -050076 bool webglCompatibility = context->getExtensions().webglCompatibility;
77
Jamie Madill51af38b2018-04-15 08:50:56 -040078 const VertexArray *vao = state.getVertexArray();
79 const AttributesMask &clientAttribs = vao->getEnabledClientMemoryAttribsMask();
80
81 if (clientAttribs.any())
82 {
83 if (webglCompatibility || !state.areClientArraysEnabled())
84 {
85 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
86 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
87 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
88 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
89 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
90 return false;
91 }
92 else if (vao->hasEnabledNullPointerClientArray())
93 {
94 // This is an application error that would normally result in a crash, but we catch it
95 // and return an error
96 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
97 return false;
98 }
99 }
100
101 // If we're drawing zero vertices, we have enough data.
102 if (vertexCount <= 0 || primcount <= 0)
103 {
104 return true;
105 }
106
Jamie Madill231c7f52017-04-26 13:45:37 -0400107 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800108 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill51af38b2018-04-15 08:50:56 -0400109
Jamie Madill02c9c042018-04-17 13:43:48 -0400110 const AttributesMask &activeAttribs = (program->getActiveAttribLocationsMask() &
111 vao->getEnabledAttributesMask() & ~clientAttribs);
Jamie Madill51af38b2018-04-15 08:50:56 -0400112
113 for (size_t attributeIndex : activeAttribs)
Jamie Madill1ca74672015-07-21 15:14:11 -0400114 {
115 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400116 ASSERT(attrib.enabled);
Corentin Wallez672f7f32017-06-15 17:42:17 -0400117
Lingfeng Yang038dd532018-03-29 17:31:52 -0700118 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400119 ASSERT(program->isAttribLocationActive(attributeIndex));
Corentin Wallezfd456442016-12-21 17:57:00 -0500120
Jamie Madill02c9c042018-04-17 13:43:48 -0400121 GLint maxVertexElement = maxVertex;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300122 GLuint divisor = binding.getDivisor();
Jamie Madill02c9c042018-04-17 13:43:48 -0400123 if (divisor != 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500124 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300125 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500126 }
127
128 // We do manual overflow checks here instead of using safe_math.h because it was
129 // a bottleneck. Thanks to some properties of GL we know inequalities that can
130 // help us make the overflow checks faster.
131
132 // The max possible attribSize is 16 for a vector of 4 32 bit values.
133 constexpr uint64_t kMaxAttribSize = 16;
134 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
135 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
136
137 // We know attribStride is given as a GLsizei which is typedefed to int.
138 // We also know an upper bound for attribSize.
Jamie Madill02c9c042018-04-17 13:43:48 -0400139 static_assert(std::is_same<int, GLsizei>::value, "Unexpected type");
140 ASSERT(ComputeVertexAttributeStride(attrib, binding) == binding.getStride());
141 uint64_t attribStride = binding.getStride();
142 ASSERT(attribStride <= kIntMax && ComputeVertexAttributeTypeSize(attrib) <= kMaxAttribSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500143
Jamie Madill02c9c042018-04-17 13:43:48 -0400144 // Computing the product of two 32-bit ints will fit in 64 bits without overflow.
145 static_assert(kIntMax * kIntMax < kUint64Max, "Unexpected overflow");
146 uint64_t attribDataSizeMinusAttribSize = maxVertexElement * attribStride;
Corentin Wallezfd456442016-12-21 17:57:00 -0500147
148 // An overflow can happen when adding the offset, check for it.
Jamie Madill02c9c042018-04-17 13:43:48 -0400149 if (attribDataSizeMinusAttribSize > kUint64Max - attrib.cachedSizePlusRelativeOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500150 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700151 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500152 return false;
153 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500154
155 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
Jamie Madill02c9c042018-04-17 13:43:48 -0400156 // We can return INVALID_OPERATION if our array buffer does not have enough backing data.
157 if (attribDataSizeMinusAttribSize + attrib.cachedSizePlusRelativeOffset >
158 binding.getCachedBufferSizeMinusOffset())
Corentin Wallezfd456442016-12-21 17:57:00 -0500159 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700160 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500161 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400162 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400163 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800164
Jamie Madill02c9c042018-04-17 13:43:48 -0400165 // TODO(jmadill): Cache this. http://anglebug.com/1391
166 if (webglCompatibility)
167 {
168 for (size_t attributeIndex : activeAttribs)
James Darpiniane8a93c62018-01-04 18:02:24 -0800169 {
Jamie Madill02c9c042018-04-17 13:43:48 -0400170 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
171 ASSERT(attrib.enabled);
172
173 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
174
175 gl::Buffer *buffer = binding.getBuffer().get();
176 if (buffer->isBoundForTransformFeedbackAndOtherUse())
177 {
178 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
179 VertexBufferBoundForTransformFeedback);
180 return false;
181 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800182 }
Jamie Madill1ca74672015-07-21 15:14:11 -0400183 }
184
185 return true;
186}
187
Jamie Madill5b772312018-03-08 20:28:32 -0500188bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400189{
190 switch (type)
191 {
192 // Types referenced in Table 3.4 of the ES 2.0.25 spec
193 case GL_UNSIGNED_BYTE:
194 case GL_UNSIGNED_SHORT_4_4_4_4:
195 case GL_UNSIGNED_SHORT_5_5_5_1:
196 case GL_UNSIGNED_SHORT_5_6_5:
197 return context->getClientVersion() >= ES_2_0;
198
199 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
200 case GL_BYTE:
201 case GL_INT:
202 case GL_SHORT:
203 case GL_UNSIGNED_INT:
204 case GL_UNSIGNED_INT_10F_11F_11F_REV:
205 case GL_UNSIGNED_INT_24_8:
206 case GL_UNSIGNED_INT_2_10_10_10_REV:
207 case GL_UNSIGNED_INT_5_9_9_9_REV:
208 case GL_UNSIGNED_SHORT:
209 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
210 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
211 return context->getClientVersion() >= ES_3_0;
212
213 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400214 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
215 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400216
217 case GL_HALF_FLOAT:
218 return context->getClientVersion() >= ES_3_0 ||
219 context->getExtensions().textureHalfFloat;
220
221 case GL_HALF_FLOAT_OES:
222 return context->getExtensions().colorBufferHalfFloat;
223
224 default:
225 return false;
226 }
227}
228
Jamie Madill5b772312018-03-08 20:28:32 -0500229bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400230{
231 switch (format)
232 {
233 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
234 case GL_RGBA:
235 case GL_RGB:
236 case GL_ALPHA:
237 return context->getClientVersion() >= ES_2_0;
238
239 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
240 case GL_RG:
241 case GL_RED:
242 case GL_RGBA_INTEGER:
243 case GL_RGB_INTEGER:
244 case GL_RG_INTEGER:
245 case GL_RED_INTEGER:
246 return context->getClientVersion() >= ES_3_0;
247
248 case GL_SRGB_ALPHA_EXT:
249 case GL_SRGB_EXT:
250 return context->getExtensions().sRGB;
251
252 case GL_BGRA_EXT:
253 return context->getExtensions().readFormatBGRA;
254
255 default:
256 return false;
257 }
258}
259
Jamie Madill5b772312018-03-08 20:28:32 -0500260bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400261 GLenum framebufferComponentType,
262 GLenum format,
263 GLenum type)
264{
265 switch (framebufferComponentType)
266 {
267 case GL_UNSIGNED_NORMALIZED:
268 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
269 // ReadPixels with BGRA even if the extension is not present
270 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
271 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
272 type == GL_UNSIGNED_BYTE);
273
274 case GL_SIGNED_NORMALIZED:
275 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
276
277 case GL_INT:
278 return (format == GL_RGBA_INTEGER && type == GL_INT);
279
280 case GL_UNSIGNED_INT:
281 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
282
283 case GL_FLOAT:
284 return (format == GL_RGBA && type == GL_FLOAT);
285
286 default:
287 UNREACHABLE();
288 return false;
289 }
290}
291
Geoff Langc1984ed2016-10-07 12:41:00 -0400292template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400293bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400294{
295 switch (ConvertToGLenum(params[0]))
296 {
297 case GL_CLAMP_TO_EDGE:
298 break;
299
300 case GL_REPEAT:
301 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400302 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400303 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400304 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 return false;
307 }
308 break;
309
310 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700311 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400312 return false;
313 }
314
315 return true;
316}
317
318template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400319bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400320{
321 switch (ConvertToGLenum(params[0]))
322 {
323 case GL_NEAREST:
324 case GL_LINEAR:
325 break;
326
327 case GL_NEAREST_MIPMAP_NEAREST:
328 case GL_LINEAR_MIPMAP_NEAREST:
329 case GL_NEAREST_MIPMAP_LINEAR:
330 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400331 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400332 {
333 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700334 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400335 return false;
336 }
337 break;
338
339 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700340 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400341 return false;
342 }
343
344 return true;
345}
346
347template <typename ParamType>
348bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
349{
350 switch (ConvertToGLenum(params[0]))
351 {
352 case GL_NEAREST:
353 case GL_LINEAR:
354 break;
355
356 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400358 return false;
359 }
360
361 return true;
362}
363
364template <typename ParamType>
365bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
366{
367 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
368 switch (ConvertToGLenum(params[0]))
369 {
370 case GL_NONE:
371 case GL_COMPARE_REF_TO_TEXTURE:
372 break;
373
374 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400376 return false;
377 }
378
379 return true;
380}
381
382template <typename ParamType>
383bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
384{
385 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
386 switch (ConvertToGLenum(params[0]))
387 {
388 case GL_LEQUAL:
389 case GL_GEQUAL:
390 case GL_LESS:
391 case GL_GREATER:
392 case GL_EQUAL:
393 case GL_NOTEQUAL:
394 case GL_ALWAYS:
395 case GL_NEVER:
396 break;
397
398 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700399 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400400 return false;
401 }
402
403 return true;
404}
405
406template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700407bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
408{
409 if (!context->getExtensions().textureSRGBDecode)
410 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700411 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700412 return false;
413 }
414
415 switch (ConvertToGLenum(params[0]))
416 {
417 case GL_DECODE_EXT:
418 case GL_SKIP_DECODE_EXT:
419 break;
420
421 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700422 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700423 return false;
424 }
425
426 return true;
427}
428
Luc Ferron1b1a8642018-01-23 15:12:01 -0500429bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
430{
431 if (!context->getExtensions().textureFilterAnisotropic)
432 {
433 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
434 return false;
435 }
436
437 return true;
438}
439
440bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
441{
442 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
443 {
444 return false;
445 }
446
447 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
448
449 if (paramValue < 1 || paramValue > largest)
450 {
451 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
452 return false;
453 }
454
455 return true;
456}
457
Jamie Madill5b772312018-03-08 20:28:32 -0500458bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400459{
460 const Program *program = context->getGLState().getProgram();
461 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
462
Brandon Jonesc405ae72017-12-06 14:15:03 -0800463 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
464 framebuffer->getDrawBufferTypeMask().to_ulong(),
465 program->getActiveOutputVariables().to_ulong(),
466 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400467 {
Brandon Jones76746f92017-11-22 11:44:41 -0800468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
469 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400470 }
471
472 return true;
473}
474
Jamie Madill5b772312018-03-08 20:28:32 -0500475bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400476{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700477 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400478 const Program *program = context->getGLState().getProgram();
479 const VertexArray *vao = context->getGLState().getVertexArray();
480
Brandon Jonesc405ae72017-12-06 14:15:03 -0800481 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
482 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
483 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
484
485 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
486 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
487 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
488
489 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
490 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400491 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800492 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
493 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400494 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400495 return true;
496}
497
Jiawei Shaofccebff2018-03-08 13:51:02 +0800498bool IsCompatibleDrawModeWithGeometryShader(GLenum drawMode,
499 GLenum geometryShaderInputPrimitiveType)
500{
501 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
502 switch (geometryShaderInputPrimitiveType)
503 {
504 case GL_POINTS:
505 return drawMode == GL_POINTS;
506 case GL_LINES:
507 return drawMode == GL_LINES || drawMode == GL_LINE_STRIP || drawMode == GL_LINE_LOOP;
508 case GL_LINES_ADJACENCY_EXT:
509 return drawMode == GL_LINES_ADJACENCY_EXT || drawMode == GL_LINE_STRIP_ADJACENCY_EXT;
510 case GL_TRIANGLES:
511 return drawMode == GL_TRIANGLES || drawMode == GL_TRIANGLE_FAN ||
512 drawMode == GL_TRIANGLE_STRIP;
513 case GL_TRIANGLES_ADJACENCY_EXT:
514 return drawMode == GL_TRIANGLES_ADJACENCY_EXT ||
515 drawMode == GL_TRIANGLE_STRIP_ADJACENCY_EXT;
516 default:
517 UNREACHABLE();
518 return false;
519 }
520}
521
Geoff Langf41a7152016-09-19 15:11:17 -0400522} // anonymous namespace
523
Brandon Jonesd1049182018-03-28 10:02:20 -0700524void SetRobustLengthParam(GLsizei *length, GLsizei value)
525{
526 if (length)
527 {
528 *length = value;
529 }
530}
531
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500532bool IsETC2EACFormat(const GLenum format)
533{
534 // ES 3.1, Table 8.19
535 switch (format)
536 {
537 case GL_COMPRESSED_R11_EAC:
538 case GL_COMPRESSED_SIGNED_R11_EAC:
539 case GL_COMPRESSED_RG11_EAC:
540 case GL_COMPRESSED_SIGNED_RG11_EAC:
541 case GL_COMPRESSED_RGB8_ETC2:
542 case GL_COMPRESSED_SRGB8_ETC2:
543 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
544 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
545 case GL_COMPRESSED_RGBA8_ETC2_EAC:
546 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
547 return true;
548
549 default:
550 return false;
551 }
552}
553
Jamie Madill5b772312018-03-08 20:28:32 -0500554bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400555{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800556 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400557 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800558 case TextureType::_2D:
559 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800560 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400561
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800562 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400563 return context->getExtensions().textureRectangle;
564
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800565 case TextureType::_3D:
566 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800567 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500568
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800569 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800570 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400571
He Yunchaoced53ae2016-11-29 15:00:51 +0800572 default:
573 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500574 }
Jamie Madill35d15012013-10-07 10:46:37 -0400575}
576
Jamie Madill5b772312018-03-08 20:28:32 -0500577bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500578{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800579 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500580 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800581 case TextureType::_2D:
582 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500583 return true;
584
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800585 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400586 return context->getExtensions().textureRectangle;
587
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500588 default:
589 return false;
590 }
591}
592
Jamie Madill5b772312018-03-08 20:28:32 -0500593bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500594{
595 switch (target)
596 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800597 case TextureType::_3D:
598 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300599 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500600
601 default:
602 return false;
603 }
604}
605
Ian Ewellbda75592016-04-18 17:25:54 -0400606// Most texture GL calls are not compatible with external textures, so we have a separate validation
607// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500608bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400609{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800610 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400611 (context->getExtensions().eglImageExternal ||
612 context->getExtensions().eglStreamConsumerExternal);
613}
614
Shannon Woods4dfed832014-03-17 20:03:39 -0400615// This function differs from ValidTextureTarget in that the target must be
616// usable as the destination of a 2D operation-- so a cube face is valid, but
617// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400618// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500619bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400620{
621 switch (target)
622 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800623 case TextureTarget::_2D:
624 case TextureTarget::CubeMapNegativeX:
625 case TextureTarget::CubeMapNegativeY:
626 case TextureTarget::CubeMapNegativeZ:
627 case TextureTarget::CubeMapPositiveX:
628 case TextureTarget::CubeMapPositiveY:
629 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800630 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800631 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400632 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800633 default:
634 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500635 }
636}
637
Jamie Madill5b772312018-03-08 20:28:32 -0500638bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -0400639 GLenum mode,
640 GLsizei count,
641 GLenum type,
642 const GLvoid *indices,
643 GLsizei primcount)
644{
645 if (primcount < 0)
646 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700647 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400648 return false;
649 }
650
651 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
652 {
653 return false;
654 }
655
Jamie Madill9fdaa492018-02-16 10:52:11 -0500656 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400657}
658
659bool ValidateDrawArraysInstancedBase(Context *context,
660 GLenum mode,
661 GLint first,
662 GLsizei count,
663 GLsizei primcount)
664{
665 if (primcount < 0)
666 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700667 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400668 return false;
669 }
670
671 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
672 {
673 return false;
674 }
675
Jamie Madill9fdaa492018-02-16 10:52:11 -0500676 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400677}
678
Jamie Madill5b772312018-03-08 20:28:32 -0500679bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400680{
681 // Verify there is at least one active attribute with a divisor of zero
682 const State &state = context->getGLState();
683
684 Program *program = state.getProgram();
685
686 const auto &attribs = state.getVertexArray()->getVertexAttributes();
687 const auto &bindings = state.getVertexArray()->getVertexBindings();
688 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
689 {
690 const VertexAttribute &attrib = attribs[attributeIndex];
691 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300692 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400693 {
694 return true;
695 }
696 }
697
Brandon Jonesafa75152017-07-21 13:11:29 -0700698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400699 return false;
700}
701
Jamie Madill5b772312018-03-08 20:28:32 -0500702bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500703{
704 switch (target)
705 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800706 case TextureType::_3D:
707 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800708 return true;
709 default:
710 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400711 }
712}
713
Jamie Madill5b772312018-03-08 20:28:32 -0500714bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800715{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800716 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800717 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800718 case TextureType::_2D:
719 case TextureType::_2DArray:
720 case TextureType::_2DMultisample:
721 case TextureType::CubeMap:
722 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800723 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800724 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400725 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800726 default:
727 return false;
728 }
729}
730
Jamie Madill5b772312018-03-08 20:28:32 -0500731bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500732{
He Yunchaoced53ae2016-11-29 15:00:51 +0800733 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
734 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400735 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500736
737 switch (target)
738 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800739 case GL_FRAMEBUFFER:
740 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400741
He Yunchaoced53ae2016-11-29 15:00:51 +0800742 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800743 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400744 return (context->getExtensions().framebufferBlit ||
745 context->getClientMajorVersion() >= 3);
746
He Yunchaoced53ae2016-11-29 15:00:51 +0800747 default:
748 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500749 }
750}
751
Jamie Madill5b772312018-03-08 20:28:32 -0500752bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400753{
Jamie Madillc29968b2016-01-20 11:17:23 -0500754 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400755 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800756 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400757 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800758 case TextureType::_2D:
759 case TextureType::_2DArray:
760 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500761 maxDimension = caps.max2DTextureSize;
762 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800763 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800764 maxDimension = caps.maxCubeMapTextureSize;
765 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800766 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400767 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800768 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800769 maxDimension = caps.max3DTextureSize;
770 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800771 default:
772 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400773 }
774
Brandon Jones6cad5662017-06-14 13:25:13 -0700775 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400776}
777
Jamie Madill5b772312018-03-08 20:28:32 -0500778bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800779 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700780 GLint level,
781 GLsizei width,
782 GLsizei height,
783 GLsizei depth,
784 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400785{
Brandon Jones6cad5662017-06-14 13:25:13 -0700786 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400787 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700788 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400789 return false;
790 }
Austin Kinross08528e12015-10-07 16:24:40 -0700791 // TexSubImage parameters can be NPOT without textureNPOT extension,
792 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500793 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500794 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500795 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400796 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400797 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700798 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400799 return false;
800 }
801
802 if (!ValidMipLevel(context, target, level))
803 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700804 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400805 return false;
806 }
807
808 return true;
809}
810
Geoff Lang966c9402017-04-18 12:38:27 -0400811bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
812{
813 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
814 (size % blockSize == 0);
815}
816
Jamie Madill5b772312018-03-08 20:28:32 -0500817bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500818 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400819 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500820 GLsizei width,
821 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400822{
Geoff Langca271392017-04-05 12:30:00 -0400823 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400824 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400825 {
826 return false;
827 }
828
Geoff Lang966c9402017-04-18 12:38:27 -0400829 if (width < 0 || height < 0)
830 {
831 return false;
832 }
833
834 if (CompressedTextureFormatRequiresExactSize(internalFormat))
835 {
836 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
837 // block size for level 0 but WebGL disallows this.
838 bool smallerThanBlockSizeAllowed =
839 level > 0 || !context->getExtensions().webglCompatibility;
840
841 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
842 smallerThanBlockSizeAllowed) ||
843 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
844 smallerThanBlockSizeAllowed))
845 {
846 return false;
847 }
848 }
849
850 return true;
851}
852
Jamie Madill5b772312018-03-08 20:28:32 -0500853bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400854 GLenum internalFormat,
855 GLint xoffset,
856 GLint yoffset,
857 GLsizei width,
858 GLsizei height,
859 size_t textureWidth,
860 size_t textureHeight)
861{
862 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
863 if (!formatInfo.compressed)
864 {
865 return false;
866 }
867
Geoff Lang44ff5a72017-02-03 15:15:43 -0500868 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400869 {
870 return false;
871 }
872
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500873 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400874 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500875 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400876 yoffset % formatInfo.compressedBlockHeight != 0)
877 {
878 return false;
879 }
880
881 // Allowed to either have data that is a multiple of block size or is smaller than the block
882 // size but fills the entire mip
883 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
884 static_cast<size_t>(width) == textureWidth &&
885 static_cast<size_t>(height) == textureHeight;
886 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
887 (height % formatInfo.compressedBlockHeight) == 0;
888 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400889 {
890 return false;
891 }
892 }
893
Geoff Langd4f180b2013-09-24 13:57:44 -0400894 return true;
895}
896
Jamie Madill5b772312018-03-08 20:28:32 -0500897bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800898 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400899 GLsizei width,
900 GLsizei height,
901 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400902 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400903 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400904 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400905 GLsizei imageSize)
906{
Corentin Wallez336129f2017-10-17 15:55:40 -0400907 gl::Buffer *pixelUnpackBuffer =
908 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400909 if (pixelUnpackBuffer == nullptr && imageSize < 0)
910 {
911 // Checks are not required
912 return true;
913 }
914
915 // ...the data would be unpacked from the buffer object such that the memory reads required
916 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400917 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
918 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400919 const gl::Extents size(width, height, depth);
920 const auto &unpack = context->getGLState().getUnpackState();
921
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800922 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400923 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
924 if (endByteOrErr.isError())
925 {
926 context->handleError(endByteOrErr.getError());
927 return false;
928 }
929
930 GLuint endByte = endByteOrErr.getResult();
931
932 if (pixelUnpackBuffer)
933 {
934 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
935 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
936 checkedEndByte += checkedOffset;
937
938 if (!checkedEndByte.IsValid() ||
939 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
940 {
941 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500942 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400943 return false;
944 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800945 if (context->getExtensions().webglCompatibility &&
946 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
947 {
948 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
949 PixelUnpackBufferBoundForTransformFeedback);
950 return false;
951 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400952 }
953 else
954 {
955 ASSERT(imageSize >= 0);
956 if (pixels == nullptr && imageSize != 0)
957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500958 context->handleError(InvalidOperation()
959 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400960 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400961 }
962
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400963 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500965 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400966 return false;
967 }
968 }
969
970 return true;
971}
972
Geoff Lang37dde692014-01-31 16:34:54 -0500973bool ValidQueryType(const Context *context, GLenum queryType)
974{
He Yunchaoced53ae2016-11-29 15:00:51 +0800975 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
976 "GL extension enums not equal.");
977 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
978 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500979
980 switch (queryType)
981 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 case GL_ANY_SAMPLES_PASSED:
983 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400984 return context->getClientMajorVersion() >= 3 ||
985 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800986 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
987 return (context->getClientMajorVersion() >= 3);
988 case GL_TIME_ELAPSED_EXT:
989 return context->getExtensions().disjointTimerQuery;
990 case GL_COMMANDS_COMPLETED_CHROMIUM:
991 return context->getExtensions().syncQuery;
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800992 case GL_PRIMITIVES_GENERATED_EXT:
993 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800994 default:
995 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500996 }
997}
998
Jamie Madill5b772312018-03-08 20:28:32 -0500999bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001000 GLenum type,
1001 GLboolean normalized,
1002 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001003 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001004 bool pureInteger)
1005{
1006 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001007 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1008 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1009 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1010 // parameter exceeds 255.
1011 constexpr GLsizei kMaxWebGLStride = 255;
1012 if (stride > kMaxWebGLStride)
1013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001014 context->handleError(InvalidValue()
1015 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001016 return false;
1017 }
1018
1019 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1020 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1021 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1022 // or an INVALID_OPERATION error is generated.
1023 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1024 size_t typeSize = GetVertexFormatTypeSize(internalType);
1025
1026 ASSERT(isPow2(typeSize) && typeSize > 0);
1027 size_t sizeMask = (typeSize - 1);
1028 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001031 return false;
1032 }
1033
1034 if ((stride & sizeMask) != 0)
1035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001036 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001037 return false;
1038 }
1039
1040 return true;
1041}
1042
Jamie Madill5b772312018-03-08 20:28:32 -05001043Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001044{
He Yunchaoced53ae2016-11-29 15:00:51 +08001045 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1046 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1047 // or program object and INVALID_OPERATION if the provided name identifies an object
1048 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001049
Dian Xiang769769a2015-09-09 15:20:08 -07001050 Program *validProgram = context->getProgram(id);
1051
1052 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001053 {
Dian Xiang769769a2015-09-09 15:20:08 -07001054 if (context->getShader(id))
1055 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001056 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001057 }
1058 else
1059 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001060 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001061 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001062 }
Dian Xiang769769a2015-09-09 15:20:08 -07001063
1064 return validProgram;
1065}
1066
Jamie Madill5b772312018-03-08 20:28:32 -05001067Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001068{
1069 // See ValidProgram for spec details.
1070
1071 Shader *validShader = context->getShader(id);
1072
1073 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001074 {
Dian Xiang769769a2015-09-09 15:20:08 -07001075 if (context->getProgram(id))
1076 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001077 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001078 }
1079 else
1080 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001081 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001082 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001083 }
Dian Xiang769769a2015-09-09 15:20:08 -07001084
1085 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001086}
1087
Geoff Langb1196682014-07-23 13:47:29 -04001088bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001089{
Geoff Langfa125c92017-10-24 13:01:46 -04001090 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001091 {
Geoff Langfa125c92017-10-24 13:01:46 -04001092 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1093 {
1094 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1095 return false;
1096 }
Jamie Madillb4472272014-07-03 10:38:55 -04001097
Geoff Langfa125c92017-10-24 13:01:46 -04001098 // Color attachment 0 is validated below because it is always valid
1099 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001100 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001101 {
Geoff Langfa125c92017-10-24 13:01:46 -04001102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001103 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001104 }
1105 }
1106 else
1107 {
1108 switch (attachment)
1109 {
Geoff Langfa125c92017-10-24 13:01:46 -04001110 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 case GL_DEPTH_ATTACHMENT:
1112 case GL_STENCIL_ATTACHMENT:
1113 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001114
He Yunchaoced53ae2016-11-29 15:00:51 +08001115 case GL_DEPTH_STENCIL_ATTACHMENT:
1116 if (!context->getExtensions().webglCompatibility &&
1117 context->getClientMajorVersion() < 3)
1118 {
Geoff Langfa125c92017-10-24 13:01:46 -04001119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
1121 }
1122 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001123
He Yunchaoced53ae2016-11-29 15:00:51 +08001124 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001125 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001126 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001127 }
1128 }
1129
1130 return true;
1131}
1132
Jamie Madill5b772312018-03-08 20:28:32 -05001133bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001134 GLenum target,
1135 GLsizei samples,
1136 GLenum internalformat,
1137 GLsizei width,
1138 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139{
1140 switch (target)
1141 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001142 case GL_RENDERBUFFER:
1143 break;
1144 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001145 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148
1149 if (width < 0 || height < 0 || samples < 0)
1150 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001151 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001152 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001153 }
1154
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001155 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1156 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1157
1158 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001159 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001161 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001162 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001163 }
1164
1165 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1166 // 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 -08001167 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001168 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1169 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
Geoff Langaae65a42014-05-26 12:43:44 -04001175 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001177 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001178 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001179 }
1180
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001181 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 if (handle == 0)
1183 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001185 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001186 }
1187
1188 return true;
1189}
1190
He Yunchaoced53ae2016-11-29 15:00:51 +08001191bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1192 GLenum target,
1193 GLenum attachment,
1194 GLenum renderbuffertarget,
1195 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001196{
Geoff Lange8afa902017-09-27 15:00:43 -04001197 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001199 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001200 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001201 }
1202
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001203 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001204
Jamie Madill84115c92015-04-23 15:00:07 -04001205 ASSERT(framebuffer);
1206 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001209 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001210 }
1211
Jamie Madillb4472272014-07-03 10:38:55 -04001212 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001213 {
Jamie Madillb4472272014-07-03 10:38:55 -04001214 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001215 }
1216
Jamie Madillab9d82c2014-01-21 16:38:14 -05001217 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1218 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1219 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1220 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1221 if (renderbuffer != 0)
1222 {
1223 if (!context->getRenderbuffer(renderbuffer))
1224 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001225 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001226 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001227 }
1228 }
1229
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001230 return true;
1231}
1232
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001233bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001234 GLint srcX0,
1235 GLint srcY0,
1236 GLint srcX1,
1237 GLint srcY1,
1238 GLint dstX0,
1239 GLint dstY0,
1240 GLint dstX1,
1241 GLint dstY1,
1242 GLbitfield mask,
1243 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001244{
1245 switch (filter)
1246 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001247 case GL_NEAREST:
1248 break;
1249 case GL_LINEAR:
1250 break;
1251 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001252 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 }
1255
1256 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001258 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001259 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260 }
1261
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1263 // color buffer, leaving only nearest being unfiltered from above
1264 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001266 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001267 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001268 }
1269
Jamie Madill51f40ec2016-06-15 14:06:00 -04001270 const auto &glState = context->getGLState();
1271 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1272 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001273
1274 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001276 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001277 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 }
1279
Jamie Madille98b1b52018-03-08 09:47:23 -05001280 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001281 {
Jamie Madill48faf802014-11-06 15:27:22 -05001282 return false;
1283 }
1284
Jamie Madille98b1b52018-03-08 09:47:23 -05001285 if (!ValidateFramebufferComplete(context, drawFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001286 {
Jamie Madill48faf802014-11-06 15:27:22 -05001287 return false;
1288 }
1289
Qin Jiajiaaef92162018-02-27 13:51:44 +08001290 if (readFramebuffer->id() == drawFramebuffer->id())
1291 {
1292 context->handleError(InvalidOperation());
1293 return false;
1294 }
1295
Jamie Madille98b1b52018-03-08 09:47:23 -05001296 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297 {
Geoff Langb1196682014-07-23 13:47:29 -04001298 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 }
1300
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1302
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001303 if (mask & GL_COLOR_BUFFER_BIT)
1304 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001305 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001306 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001307
He Yunchao66a41a22016-12-15 16:45:05 +08001308 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001309 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001310 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001311
Geoff Langa15472a2015-08-11 11:48:03 -04001312 for (size_t drawbufferIdx = 0;
1313 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314 {
Geoff Langa15472a2015-08-11 11:48:03 -04001315 const FramebufferAttachment *attachment =
1316 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1317 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001318 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001319 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320
Geoff Langb2f3d052013-08-13 12:49:27 -04001321 // The GL ES 3.0.2 spec (pg 193) states that:
1322 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001323 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1324 // as well
1325 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1326 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001327 // Changes with EXT_color_buffer_float:
1328 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001329 GLenum readComponentType = readFormat.info->componentType;
1330 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001331 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001332 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001333 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001334 drawComponentType == GL_SIGNED_NORMALIZED);
1335
1336 if (extensions.colorBufferFloat)
1337 {
1338 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1339 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1340
1341 if (readFixedOrFloat != drawFixedOrFloat)
1342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 context->handleError(InvalidOperation()
1344 << "If the read buffer contains fixed-point or "
1345 "floating-point values, the draw buffer must "
1346 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001347 return false;
1348 }
1349 }
1350 else if (readFixedPoint != drawFixedPoint)
1351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001352 context->handleError(InvalidOperation()
1353 << "If the read buffer contains fixed-point values, "
1354 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001355 return false;
1356 }
1357
1358 if (readComponentType == GL_UNSIGNED_INT &&
1359 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001362 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 }
1364
Jamie Madill6163c752015-12-07 16:32:59 -05001365 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001367 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001368 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 }
1370
Jamie Madilla3944d42016-07-22 22:13:26 -04001371 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001372 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001374 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001375 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376 }
Geoff Lange4915782017-04-12 15:19:07 -04001377
1378 if (context->getExtensions().webglCompatibility &&
1379 *readColorBuffer == *attachment)
1380 {
1381 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001382 InvalidOperation()
1383 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001384 return false;
1385 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386 }
1387 }
1388
Jamie Madilla3944d42016-07-22 22:13:26 -04001389 if ((readFormat.info->componentType == GL_INT ||
1390 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1391 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001393 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001394 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 }
He Yunchao66a41a22016-12-15 16:45:05 +08001397 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1398 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1399 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1400 // situation is an application error that would lead to a crash in ANGLE.
1401 else if (drawFramebuffer->hasEnabledDrawBuffer())
1402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 context->handleError(
1404 InvalidOperation()
1405 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001406 return false;
1407 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 }
1409
He Yunchaoced53ae2016-11-29 15:00:51 +08001410 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001411 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1412 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001414 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001415 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001416 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001417 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001418 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001419 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001420
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001421 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 {
Kenneth Russell69382852017-07-21 16:38:44 -04001423 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001425 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001426 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001429 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001432 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 }
Geoff Lange4915782017-04-12 15:19:07 -04001434
1435 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001437 context->handleError(
1438 InvalidOperation()
1439 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001440 return false;
1441 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001442 }
He Yunchao66a41a22016-12-15 16:45:05 +08001443 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1444 else if (drawBuffer)
1445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001446 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1447 "depth/stencil attachment of a "
1448 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001449 return false;
1450 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001451 }
1452 }
1453
Martin Radeva3ed4572017-07-27 18:29:37 +03001454 // ANGLE_multiview, Revision 1:
1455 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1456 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1457 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1458 {
1459 context->handleError(InvalidFramebufferOperation()
1460 << "Attempt to read from a multi-view framebuffer.");
1461 return false;
1462 }
1463 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1464 {
1465 context->handleError(InvalidFramebufferOperation()
1466 << "Attempt to write to a multi-view framebuffer.");
1467 return false;
1468 }
1469
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001470 return true;
1471}
1472
Jamie Madill4928b7c2017-06-20 12:57:39 -04001473bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001474 GLint x,
1475 GLint y,
1476 GLsizei width,
1477 GLsizei height,
1478 GLenum format,
1479 GLenum type,
1480 GLsizei bufSize,
1481 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001482 GLsizei *columns,
1483 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001484 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001485{
1486 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001487 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001488 return false;
1489 }
1490
Brandon Jonesd1049182018-03-28 10:02:20 -07001491 GLsizei writeLength = 0;
1492 GLsizei writeColumns = 0;
1493 GLsizei writeRows = 0;
1494
1495 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1496 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001497 {
Geoff Langb1196682014-07-23 13:47:29 -04001498 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001499 }
1500
Brandon Jonesd1049182018-03-28 10:02:20 -07001501 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001502 {
Geoff Langb1196682014-07-23 13:47:29 -04001503 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001504 }
1505
Brandon Jonesd1049182018-03-28 10:02:20 -07001506 SetRobustLengthParam(length, writeLength);
1507 SetRobustLengthParam(columns, writeColumns);
1508 SetRobustLengthParam(rows, writeRows);
1509
Jamie Madillc29968b2016-01-20 11:17:23 -05001510 return true;
1511}
1512
1513bool ValidateReadnPixelsEXT(Context *context,
1514 GLint x,
1515 GLint y,
1516 GLsizei width,
1517 GLsizei height,
1518 GLenum format,
1519 GLenum type,
1520 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001521 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001522{
1523 if (bufSize < 0)
1524 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001525 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001526 return false;
1527 }
1528
Geoff Lang62fce5b2016-09-30 10:46:35 -04001529 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001530 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001531}
Jamie Madill26e91952014-03-05 15:01:27 -05001532
Jamie Madill4928b7c2017-06-20 12:57:39 -04001533bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001534 GLint x,
1535 GLint y,
1536 GLsizei width,
1537 GLsizei height,
1538 GLenum format,
1539 GLenum type,
1540 GLsizei bufSize,
1541 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001542 GLsizei *columns,
1543 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001544 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001545{
Brandon Jonesd1049182018-03-28 10:02:20 -07001546 GLsizei writeLength = 0;
1547 GLsizei writeColumns = 0;
1548 GLsizei writeRows = 0;
1549
Geoff Lang62fce5b2016-09-30 10:46:35 -04001550 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001551 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001552 return false;
1553 }
1554
Brandon Jonesd1049182018-03-28 10:02:20 -07001555 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1556 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001557 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001558 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001559 }
1560
Brandon Jonesd1049182018-03-28 10:02:20 -07001561 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001562 {
1563 return false;
1564 }
1565
Brandon Jonesd1049182018-03-28 10:02:20 -07001566 SetRobustLengthParam(length, writeLength);
1567 SetRobustLengthParam(columns, writeColumns);
1568 SetRobustLengthParam(rows, writeRows);
1569
Geoff Lang62fce5b2016-09-30 10:46:35 -04001570 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001571}
1572
Jamie Madillf0e04492017-08-26 15:28:42 -04001573bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001574{
1575 if (!context->getExtensions().occlusionQueryBoolean &&
1576 !context->getExtensions().disjointTimerQuery)
1577 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001578 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001579 return false;
1580 }
1581
Olli Etuaho41997e72016-03-10 13:38:39 +02001582 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001583}
1584
Jamie Madillf0e04492017-08-26 15:28:42 -04001585bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001586{
1587 if (!context->getExtensions().occlusionQueryBoolean &&
1588 !context->getExtensions().disjointTimerQuery)
1589 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001590 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001591 return false;
1592 }
1593
Olli Etuaho41997e72016-03-10 13:38:39 +02001594 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001595}
1596
Jamie Madillf0e04492017-08-26 15:28:42 -04001597bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1598{
1599 if (!context->getExtensions().occlusionQueryBoolean &&
1600 !context->getExtensions().disjointTimerQuery)
1601 {
1602 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1603 return false;
1604 }
1605
1606 return true;
1607}
1608
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001609bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001610{
1611 if (!ValidQueryType(context, target))
1612 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001613 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001614 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001615 }
1616
1617 if (id == 0)
1618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001619 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001620 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001621 }
1622
1623 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1624 // of zero, if the active query object name for <target> is non-zero (for the
1625 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1626 // the active query for either target is non-zero), if <id> is the name of an
1627 // existing query object whose type does not match <target>, or if <id> is the
1628 // active query object name for any query type, the error INVALID_OPERATION is
1629 // generated.
1630
1631 // Ensure no other queries are active
1632 // NOTE: If other queries than occlusion are supported, we will need to check
1633 // separately that:
1634 // a) The query ID passed is not the current active query for any target/type
1635 // b) There are no active queries for the requested target (and in the case
1636 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1637 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001638
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001639 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001642 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001643 }
1644
1645 Query *queryObject = context->getQuery(id, true, target);
1646
1647 // check that name was obtained with glGenQueries
1648 if (!queryObject)
1649 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001650 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001651 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001652 }
1653
1654 // check for type mismatch
1655 if (queryObject->getType() != target)
1656 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001657 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001658 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001659 }
1660
1661 return true;
1662}
1663
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001664bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1665{
1666 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001667 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001668 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001669 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670 return false;
1671 }
1672
1673 return ValidateBeginQueryBase(context, target, id);
1674}
1675
1676bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001677{
1678 if (!ValidQueryType(context, target))
1679 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001680 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001681 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001682 }
1683
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001684 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001685
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001686 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001688 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001689 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001690 }
1691
Jamie Madill45c785d2014-05-13 14:09:34 -04001692 return true;
1693}
1694
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001695bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1696{
1697 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001698 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001699 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001700 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001701 return false;
1702 }
1703
1704 return ValidateEndQueryBase(context, target);
1705}
1706
1707bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1708{
1709 if (!context->getExtensions().disjointTimerQuery)
1710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001711 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001712 return false;
1713 }
1714
1715 if (target != GL_TIMESTAMP_EXT)
1716 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001717 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001718 return false;
1719 }
1720
1721 Query *queryObject = context->getQuery(id, true, target);
1722 if (queryObject == nullptr)
1723 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001724 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001725 return false;
1726 }
1727
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001728 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001729 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001730 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 return false;
1732 }
1733
1734 return true;
1735}
1736
Geoff Lang2186c382016-10-14 10:54:54 -04001737bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001738{
Geoff Lang2186c382016-10-14 10:54:54 -04001739 if (numParams)
1740 {
1741 *numParams = 0;
1742 }
1743
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1745 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001746 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001747 return false;
1748 }
1749
1750 switch (pname)
1751 {
1752 case GL_CURRENT_QUERY_EXT:
1753 if (target == GL_TIMESTAMP_EXT)
1754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001755 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001756 return false;
1757 }
1758 break;
1759 case GL_QUERY_COUNTER_BITS_EXT:
1760 if (!context->getExtensions().disjointTimerQuery ||
1761 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1762 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001763 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001764 return false;
1765 }
1766 break;
1767 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001768 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769 return false;
1770 }
1771
Geoff Lang2186c382016-10-14 10:54:54 -04001772 if (numParams)
1773 {
1774 // All queries return only one value
1775 *numParams = 1;
1776 }
1777
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001778 return true;
1779}
1780
1781bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1782{
1783 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001784 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001785 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001786 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001787 return false;
1788 }
1789
Geoff Lang2186c382016-10-14 10:54:54 -04001790 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001791}
1792
Geoff Lang2186c382016-10-14 10:54:54 -04001793bool ValidateGetQueryivRobustANGLE(Context *context,
1794 GLenum target,
1795 GLenum pname,
1796 GLsizei bufSize,
1797 GLsizei *length,
1798 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001799{
Geoff Lang2186c382016-10-14 10:54:54 -04001800 if (!ValidateRobustEntryPoint(context, bufSize))
1801 {
1802 return false;
1803 }
1804
Brandon Jonesd1049182018-03-28 10:02:20 -07001805 GLsizei numParams = 0;
1806
1807 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001808 {
1809 return false;
1810 }
1811
Brandon Jonesd1049182018-03-28 10:02:20 -07001812 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001813 {
1814 return false;
1815 }
1816
Brandon Jonesd1049182018-03-28 10:02:20 -07001817 SetRobustLengthParam(length, numParams);
1818
Geoff Lang2186c382016-10-14 10:54:54 -04001819 return true;
1820}
1821
1822bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1823{
1824 if (numParams)
1825 {
1826 *numParams = 0;
1827 }
1828
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001829 Query *queryObject = context->getQuery(id, false, GL_NONE);
1830
1831 if (!queryObject)
1832 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001833 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001834 return false;
1835 }
1836
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001837 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001838 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001839 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001840 return false;
1841 }
1842
1843 switch (pname)
1844 {
1845 case GL_QUERY_RESULT_EXT:
1846 case GL_QUERY_RESULT_AVAILABLE_EXT:
1847 break;
1848
1849 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001850 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001851 return false;
1852 }
1853
Geoff Lang2186c382016-10-14 10:54:54 -04001854 if (numParams)
1855 {
1856 *numParams = 1;
1857 }
1858
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001859 return true;
1860}
1861
1862bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1863{
1864 if (!context->getExtensions().disjointTimerQuery)
1865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001866 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001867 return false;
1868 }
Geoff Lang2186c382016-10-14 10:54:54 -04001869 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1870}
1871
1872bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1873 GLuint id,
1874 GLenum pname,
1875 GLsizei bufSize,
1876 GLsizei *length,
1877 GLint *params)
1878{
1879 if (!context->getExtensions().disjointTimerQuery)
1880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001881 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001882 return false;
1883 }
1884
1885 if (!ValidateRobustEntryPoint(context, bufSize))
1886 {
1887 return false;
1888 }
1889
Brandon Jonesd1049182018-03-28 10:02:20 -07001890 GLsizei numParams = 0;
1891
1892 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001893 {
1894 return false;
1895 }
1896
Brandon Jonesd1049182018-03-28 10:02:20 -07001897 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001898 {
1899 return false;
1900 }
1901
Brandon Jonesd1049182018-03-28 10:02:20 -07001902 SetRobustLengthParam(length, numParams);
1903
Geoff Lang2186c382016-10-14 10:54:54 -04001904 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001905}
1906
1907bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1908{
1909 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001910 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001911 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001913 return false;
1914 }
Geoff Lang2186c382016-10-14 10:54:54 -04001915 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1916}
1917
1918bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1919 GLuint id,
1920 GLenum pname,
1921 GLsizei bufSize,
1922 GLsizei *length,
1923 GLuint *params)
1924{
1925 if (!context->getExtensions().disjointTimerQuery &&
1926 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1927 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001928 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001929 return false;
1930 }
1931
1932 if (!ValidateRobustEntryPoint(context, bufSize))
1933 {
1934 return false;
1935 }
1936
Brandon Jonesd1049182018-03-28 10:02:20 -07001937 GLsizei numParams = 0;
1938
1939 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001940 {
1941 return false;
1942 }
1943
Brandon Jonesd1049182018-03-28 10:02:20 -07001944 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001945 {
1946 return false;
1947 }
1948
Brandon Jonesd1049182018-03-28 10:02:20 -07001949 SetRobustLengthParam(length, numParams);
1950
Geoff Lang2186c382016-10-14 10:54:54 -04001951 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001952}
1953
1954bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1955{
1956 if (!context->getExtensions().disjointTimerQuery)
1957 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001958 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001959 return false;
1960 }
Geoff Lang2186c382016-10-14 10:54:54 -04001961 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1962}
1963
1964bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1965 GLuint id,
1966 GLenum pname,
1967 GLsizei bufSize,
1968 GLsizei *length,
1969 GLint64 *params)
1970{
1971 if (!context->getExtensions().disjointTimerQuery)
1972 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001973 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001974 return false;
1975 }
1976
1977 if (!ValidateRobustEntryPoint(context, bufSize))
1978 {
1979 return false;
1980 }
1981
Brandon Jonesd1049182018-03-28 10:02:20 -07001982 GLsizei numParams = 0;
1983
1984 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001985 {
1986 return false;
1987 }
1988
Brandon Jonesd1049182018-03-28 10:02:20 -07001989 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001990 {
1991 return false;
1992 }
1993
Brandon Jonesd1049182018-03-28 10:02:20 -07001994 SetRobustLengthParam(length, numParams);
1995
Geoff Lang2186c382016-10-14 10:54:54 -04001996 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001997}
1998
1999bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2000{
2001 if (!context->getExtensions().disjointTimerQuery)
2002 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002003 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002004 return false;
2005 }
Geoff Lang2186c382016-10-14 10:54:54 -04002006 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2007}
2008
2009bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2010 GLuint id,
2011 GLenum pname,
2012 GLsizei bufSize,
2013 GLsizei *length,
2014 GLuint64 *params)
2015{
2016 if (!context->getExtensions().disjointTimerQuery)
2017 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002018 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002019 return false;
2020 }
2021
2022 if (!ValidateRobustEntryPoint(context, bufSize))
2023 {
2024 return false;
2025 }
2026
Brandon Jonesd1049182018-03-28 10:02:20 -07002027 GLsizei numParams = 0;
2028
2029 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002030 {
2031 return false;
2032 }
2033
Brandon Jonesd1049182018-03-28 10:02:20 -07002034 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002035 {
2036 return false;
2037 }
2038
Brandon Jonesd1049182018-03-28 10:02:20 -07002039 SetRobustLengthParam(length, numParams);
2040
Geoff Lang2186c382016-10-14 10:54:54 -04002041 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002042}
2043
Jamie Madill5b772312018-03-08 20:28:32 -05002044bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002045 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002046 GLint location,
2047 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002048 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002049{
Jiajia Qin5451d532017-11-16 17:16:34 +08002050 // TODO(Jiajia): Add image uniform check in future.
2051 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002052 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002053 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002054 return false;
2055 }
2056
Jiajia Qin5451d532017-11-16 17:16:34 +08002057 if (!program)
2058 {
2059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2060 return false;
2061 }
2062
2063 if (!program->isLinked())
2064 {
2065 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2066 return false;
2067 }
2068
2069 if (location == -1)
2070 {
2071 // Silently ignore the uniform command
2072 return false;
2073 }
2074
2075 const auto &uniformLocations = program->getUniformLocations();
2076 size_t castedLocation = static_cast<size_t>(location);
2077 if (castedLocation >= uniformLocations.size())
2078 {
2079 context->handleError(InvalidOperation() << "Invalid uniform location");
2080 return false;
2081 }
2082
2083 const auto &uniformLocation = uniformLocations[castedLocation];
2084 if (uniformLocation.ignored)
2085 {
2086 // Silently ignore the uniform command
2087 return false;
2088 }
2089
2090 if (!uniformLocation.used())
2091 {
2092 context->handleError(InvalidOperation());
2093 return false;
2094 }
2095
2096 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2097
2098 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2099 if (!uniform.isArray() && count > 1)
2100 {
2101 context->handleError(InvalidOperation());
2102 return false;
2103 }
2104
2105 *uniformOut = &uniform;
2106 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002107}
2108
Jamie Madill5b772312018-03-08 20:28:32 -05002109bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002110 GLenum uniformType,
2111 GLsizei count,
2112 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002113{
Jiajia Qin5451d532017-11-16 17:16:34 +08002114 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2115 // It is compatible with INT or BOOL.
2116 // Do these cheap tests first, for a little extra speed.
2117 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002118 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002119 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002120 }
2121
Jiajia Qin5451d532017-11-16 17:16:34 +08002122 if (IsSamplerType(uniformType))
2123 {
2124 // Check that the values are in range.
2125 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2126 for (GLsizei i = 0; i < count; ++i)
2127 {
2128 if (value[i] < 0 || value[i] >= max)
2129 {
2130 context->handleError(InvalidValue() << "sampler uniform value out of range");
2131 return false;
2132 }
2133 }
2134 return true;
2135 }
2136
2137 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2138 return false;
2139}
2140
Jamie Madill5b772312018-03-08 20:28:32 -05002141bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002142{
2143 // Check that the value type is compatible with uniform type.
2144 // Do the cheaper test first, for a little extra speed.
2145 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2146 {
2147 return true;
2148 }
2149
2150 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2151 return false;
2152}
2153
Jamie Madill5b772312018-03-08 20:28:32 -05002154bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002155{
2156 // Check that the value type is compatible with uniform type.
2157 if (valueType == uniformType)
2158 {
2159 return true;
2160 }
2161
2162 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2163 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002164}
2165
Jamie Madill5b772312018-03-08 20:28:32 -05002166bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002167{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002168 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002169 gl::Program *programObject = context->getGLState().getProgram();
2170 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2171 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002172}
2173
Jamie Madill5b772312018-03-08 20:28:32 -05002174bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002175{
2176 const LinkedUniform *uniform = nullptr;
2177 gl::Program *programObject = context->getGLState().getProgram();
2178 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2179 ValidateUniform1ivValue(context, uniform->type, count, value);
2180}
2181
Jamie Madill5b772312018-03-08 20:28:32 -05002182bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002183 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002184 GLint location,
2185 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002186 GLboolean transpose)
2187{
Geoff Lang92019432017-11-20 13:09:34 -05002188 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002190 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002191 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002192 }
2193
Jamie Madill62d31cb2015-09-11 13:25:51 -04002194 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002195 gl::Program *programObject = context->getGLState().getProgram();
2196 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2197 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002198}
2199
Jamie Madill5b772312018-03-08 20:28:32 -05002200bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002201{
2202 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002204 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002205 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002206 }
2207
Jamie Madill0af26e12015-03-05 19:54:33 -05002208 const Caps &caps = context->getCaps();
2209
Jamie Madill893ab082014-05-16 16:56:10 -04002210 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2211 {
2212 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2213
Jamie Madill0af26e12015-03-05 19:54:33 -05002214 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002215 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002216 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002217 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002218 }
2219 }
2220
2221 switch (pname)
2222 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002223 case GL_TEXTURE_BINDING_2D:
2224 case GL_TEXTURE_BINDING_CUBE_MAP:
2225 case GL_TEXTURE_BINDING_3D:
2226 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002227 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002228 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002229 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2230 if (!context->getExtensions().textureRectangle)
2231 {
2232 context->handleError(InvalidEnum()
2233 << "ANGLE_texture_rectangle extension not present");
2234 return false;
2235 }
2236 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002237 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2238 if (!context->getExtensions().eglStreamConsumerExternal &&
2239 !context->getExtensions().eglImageExternal)
2240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002241 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2242 "nor GL_OES_EGL_image_external "
2243 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002244 return false;
2245 }
2246 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002247
He Yunchaoced53ae2016-11-29 15:00:51 +08002248 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2249 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002250 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002251 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2252 ASSERT(readFramebuffer);
2253
2254 if (!ValidateFramebufferComplete(context, readFramebuffer, false))
Jamie Madill893ab082014-05-16 16:56:10 -04002255 {
Geoff Langb1196682014-07-23 13:47:29 -04002256 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002257 }
2258
Jamie Madille98b1b52018-03-08 09:47:23 -05002259 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002260 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002261 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002262 return false;
2263 }
2264
Jamie Madille98b1b52018-03-08 09:47:23 -05002265 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002266 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002268 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002269 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002270 }
2271 }
2272 break;
2273
He Yunchaoced53ae2016-11-29 15:00:51 +08002274 default:
2275 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002276 }
2277
2278 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002279 if (*numParams == 0)
2280 {
2281 return false;
2282 }
2283
2284 return true;
2285}
2286
Brandon Jonesd1049182018-03-28 10:02:20 -07002287bool ValidateGetBooleanvRobustANGLE(Context *context,
2288 GLenum pname,
2289 GLsizei bufSize,
2290 GLsizei *length,
2291 GLboolean *params)
2292{
2293 GLenum nativeType;
2294 unsigned int numParams = 0;
2295
2296 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2297 {
2298 return false;
2299 }
2300
2301 SetRobustLengthParam(length, numParams);
2302
2303 return true;
2304}
2305
2306bool ValidateGetFloatvRobustANGLE(Context *context,
2307 GLenum pname,
2308 GLsizei bufSize,
2309 GLsizei *length,
2310 GLfloat *params)
2311{
2312 GLenum nativeType;
2313 unsigned int numParams = 0;
2314
2315 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2316 {
2317 return false;
2318 }
2319
2320 SetRobustLengthParam(length, numParams);
2321
2322 return true;
2323}
2324
2325bool ValidateGetIntegervRobustANGLE(Context *context,
2326 GLenum pname,
2327 GLsizei bufSize,
2328 GLsizei *length,
2329 GLint *data)
2330{
2331 GLenum nativeType;
2332 unsigned int numParams = 0;
2333
2334 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2335 {
2336 return false;
2337 }
2338
2339 SetRobustLengthParam(length, numParams);
2340
2341 return true;
2342}
2343
2344bool ValidateGetInteger64vRobustANGLE(Context *context,
2345 GLenum pname,
2346 GLsizei bufSize,
2347 GLsizei *length,
2348 GLint64 *data)
2349{
2350 GLenum nativeType;
2351 unsigned int numParams = 0;
2352
2353 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2354 {
2355 return false;
2356 }
2357
2358 if (nativeType == GL_INT_64_ANGLEX)
2359 {
2360 CastStateValues(context, nativeType, pname, numParams, data);
2361 return false;
2362 }
2363
2364 SetRobustLengthParam(length, numParams);
2365 return true;
2366}
2367
Jamie Madill5b772312018-03-08 20:28:32 -05002368bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002369 GLenum pname,
2370 GLsizei bufSize,
2371 GLenum *nativeType,
2372 unsigned int *numParams)
2373{
2374 if (!ValidateRobustEntryPoint(context, bufSize))
2375 {
2376 return false;
2377 }
2378
2379 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2380 {
2381 return false;
2382 }
2383
2384 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002385 {
2386 return false;
2387 }
2388
2389 return true;
2390}
2391
Jamie Madill5b772312018-03-08 20:28:32 -05002392bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002393 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002394 GLint level,
2395 GLenum internalformat,
2396 bool isSubImage,
2397 GLint xoffset,
2398 GLint yoffset,
2399 GLint zoffset,
2400 GLint x,
2401 GLint y,
2402 GLsizei width,
2403 GLsizei height,
2404 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002405 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002406{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002407 TextureType texType = TextureTargetToType(target);
2408
Brandon Jones6cad5662017-06-14 13:25:13 -07002409 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002410 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002411 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2412 return false;
2413 }
2414
2415 if (width < 0 || height < 0)
2416 {
2417 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002418 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002419 }
2420
He Yunchaoced53ae2016-11-29 15:00:51 +08002421 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2422 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002424 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002425 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002426 }
2427
2428 if (border != 0)
2429 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002430 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002431 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002432 }
2433
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002434 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002435 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002436 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002437 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002438 }
2439
Jamie Madille98b1b52018-03-08 09:47:23 -05002440 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002441 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madille98b1b52018-03-08 09:47:23 -05002442 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill560a8d82014-05-21 13:06:20 -04002443 {
Geoff Langb1196682014-07-23 13:47:29 -04002444 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002445 }
2446
Jamie Madille98b1b52018-03-08 09:47:23 -05002447 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002448 {
Geoff Langb1196682014-07-23 13:47:29 -04002449 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002450 }
2451
Martin Radev138064f2016-07-15 12:03:41 +03002452 if (readFramebuffer->getReadBufferState() == GL_NONE)
2453 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002454 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002455 return false;
2456 }
2457
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002458 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2459 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002460 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002461 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002462 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2463 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002464 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002466 return false;
2467 }
2468
Martin Radev04e2c3b2017-07-27 16:54:35 +03002469 // ANGLE_multiview spec, Revision 1:
2470 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2471 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2472 // is not NONE.
2473 if (source->getMultiviewLayout() != GL_NONE)
2474 {
2475 context->handleError(InvalidFramebufferOperation()
2476 << "The active read framebuffer object has multiview attachments.");
2477 return false;
2478 }
2479
Geoff Langaae65a42014-05-26 12:43:44 -04002480 const gl::Caps &caps = context->getCaps();
2481
Geoff Langaae65a42014-05-26 12:43:44 -04002482 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002483 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002484 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002485 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002486 maxDimension = caps.max2DTextureSize;
2487 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002488
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002489 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002490 maxDimension = caps.maxCubeMapTextureSize;
2491 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002492
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002493 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002494 maxDimension = caps.maxRectangleTextureSize;
2495 break;
2496
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002497 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002498 maxDimension = caps.max2DTextureSize;
2499 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002500
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002501 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002502 maxDimension = caps.max3DTextureSize;
2503 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002504
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002506 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002507 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002508 }
2509
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002510 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002511 if (!texture)
2512 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002513 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002514 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002515 }
2516
Geoff Lang69cce582015-09-17 13:20:36 -04002517 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002519 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002520 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002521 }
2522
Geoff Langca271392017-04-05 12:30:00 -04002523 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002524 isSubImage ? *texture->getFormat(target, level).info
2525 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002526
Geoff Lang966c9402017-04-18 12:38:27 -04002527 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002529 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002530 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002531 }
2532
2533 if (isSubImage)
2534 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002535 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2536 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2537 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002539 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002540 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002541 }
2542 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002543 else
2544 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002545 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002546 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002547 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002548 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002549 }
2550
Geoff Langeb66a6e2016-10-31 13:06:12 -04002551 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002552 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002553 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002554 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002555 }
2556
2557 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002558 if (static_cast<int>(width) > maxLevelDimension ||
2559 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002560 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002561 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002562 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002563 }
2564 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002565
Jamie Madill0c8abca2016-07-22 20:21:26 -04002566 if (textureFormatOut)
2567 {
2568 *textureFormatOut = texture->getFormat(target, level);
2569 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002570
2571 // Detect texture copying feedback loops for WebGL.
2572 if (context->getExtensions().webglCompatibility)
2573 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002574 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002575 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002576 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002577 return false;
2578 }
2579 }
2580
Jamie Madill560a8d82014-05-21 13:06:20 -04002581 return true;
2582}
2583
Jamie Madill5b772312018-03-08 20:28:32 -05002584bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002585{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002586 const Extensions &extensions = context->getExtensions();
2587
Jamie Madill1aeb1312014-06-20 13:21:25 -04002588 switch (mode)
2589 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002590 case GL_POINTS:
2591 case GL_LINES:
2592 case GL_LINE_LOOP:
2593 case GL_LINE_STRIP:
2594 case GL_TRIANGLES:
2595 case GL_TRIANGLE_STRIP:
2596 case GL_TRIANGLE_FAN:
2597 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002598
2599 case GL_LINES_ADJACENCY_EXT:
2600 case GL_LINE_STRIP_ADJACENCY_EXT:
2601 case GL_TRIANGLES_ADJACENCY_EXT:
2602 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2603 if (!extensions.geometryShader)
2604 {
2605 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2606 return false;
2607 }
2608 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002609 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002610 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002611 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002612 }
2613
Jamie Madill250d33f2014-06-06 17:09:03 -04002614 if (count < 0)
2615 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002616 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002617 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002618 }
2619
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002620 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002621
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002622 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2623 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2624 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2625 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002626 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002627 // Check for mapped buffers
2628 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002629 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002630 {
2631 context->handleError(InvalidOperation());
2632 return false;
2633 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002634 }
2635
Jamie Madillcbcde722017-01-06 14:50:00 -05002636 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2637 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002638 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002639 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002640 {
Ken Russellb9f92502018-01-27 19:00:26 -08002641 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002642 const FramebufferAttachment *dsAttachment =
2643 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002644 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2645 ASSERT(stencilBits <= 8);
2646
Jinyoung Hur85769f02015-10-20 17:08:44 -04002647 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002648 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002649 {
Ken Russellb9f92502018-01-27 19:00:26 -08002650 GLuint maxStencilValue = (1 << stencilBits) - 1;
2651
2652 bool differentRefs =
2653 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2654 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2655 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2656 (depthStencilState.stencilBackWritemask & maxStencilValue);
2657 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2658 (depthStencilState.stencilBackMask & maxStencilValue);
2659
2660 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002661 {
Ken Russellb9f92502018-01-27 19:00:26 -08002662 if (!extensions.webglCompatibility)
2663 {
2664 ERR() << "This ANGLE implementation does not support separate front/back "
2665 "stencil writemasks, reference values, or stencil mask values.";
2666 }
2667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2668 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002669 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002670 }
Jamie Madillac528012014-06-20 13:21:23 -04002671 }
2672
Jamie Madille98b1b52018-03-08 09:47:23 -05002673 if (!ValidateFramebufferComplete(context, framebuffer, true))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002674 {
Geoff Langb1196682014-07-23 13:47:29 -04002675 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002676 }
2677
Geoff Lang7dd2e102014-11-10 15:19:26 -05002678 gl::Program *program = state.getProgram();
2679 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002680 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002681 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002682 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002683 }
2684
Yunchao Hecddcb592017-11-13 15:27:35 +08002685 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2686 // vertex shader stage or fragment shader stage is a undefined behaviour.
2687 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2688 // produce undefined result.
Jiawei Shao385b3e02018-03-21 09:43:28 +08002689 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2690 !program->hasLinkedShaderStage(ShaderType::Fragment))
Yunchao Hecddcb592017-11-13 15:27:35 +08002691 {
2692 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2693 "vertex shader stage or fragment shader stage.");
2694 return false;
2695 }
2696
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002697 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002699 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002700 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002701 }
2702
Martin Radevffe754b2017-07-31 10:38:07 +03002703 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002704 {
Martin Radevda8e2572017-09-12 17:21:16 +03002705 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002706 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002707 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002708 {
2709 context->handleError(InvalidOperation() << "The number of views in the active program "
2710 "and draw framebuffer does not match.");
2711 return false;
2712 }
Martin Radev7e69f762017-07-27 14:54:13 +03002713
2714 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2715 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2716 framebufferNumViews > 1)
2717 {
2718 context->handleError(InvalidOperation()
2719 << "There is an active transform feedback object "
2720 "when the number of views in the active draw "
2721 "framebuffer is greater than 1.");
2722 return false;
2723 }
Martin Radevffe754b2017-07-31 10:38:07 +03002724
2725 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2726 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2727 {
2728 context->handleError(InvalidOperation() << "There is an active query for target "
2729 "GL_TIME_ELAPSED_EXT when the number of "
2730 "views in the active draw framebuffer is "
2731 "greater than 1.");
2732 return false;
2733 }
Martin Radev7cf61662017-07-26 17:10:53 +03002734 }
2735
Jiawei Shaofccebff2018-03-08 13:51:02 +08002736 // Do geometry shader specific validations
Jiawei Shao385b3e02018-03-21 09:43:28 +08002737 if (program->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shaofccebff2018-03-08 13:51:02 +08002738 {
2739 if (!IsCompatibleDrawModeWithGeometryShader(mode,
2740 program->getGeometryShaderInputPrimitiveType()))
2741 {
2742 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2743 IncompatibleDrawModeAgainstGeometryShader);
2744 return false;
2745 }
2746 }
2747
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002748 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002749 for (unsigned int uniformBlockIndex = 0;
2750 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002751 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002752 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Lingfeng Yang038dd532018-03-29 17:31:52 -07002753 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002754 const OffsetBindingPointer<Buffer> &uniformBuffer =
2755 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002756
Geoff Lang5d124a62015-09-15 13:03:27 -04002757 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002758 {
2759 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002760 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002761 InvalidOperation()
2762 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002763 return false;
2764 }
2765
James Darpinian30b604d2018-03-12 17:26:57 -07002766 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002767 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002768 {
2769 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002770 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002771 InvalidOperation()
2772 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002773 return false;
2774 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002775
2776 if (extensions.webglCompatibility &&
2777 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2778 {
2779 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2780 UniformBufferBoundForTransformFeedback);
2781 return false;
2782 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002783 }
2784
Geoff Lange0cff192017-05-30 13:04:56 -04002785 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002786 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002787 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002788 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2789 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2790 transformFeedbackObject->buffersBoundForOtherUse())
2791 {
2792 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2793 return false;
2794 }
Geoff Lange0cff192017-05-30 13:04:56 -04002795 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002796 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2797 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002798 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002799 return false;
2800 }
Geoff Lange0cff192017-05-30 13:04:56 -04002801
Geoff Lang9ab5b822017-05-30 16:19:23 -04002802 // Detect that the vertex shader input types match the attribute types
2803 if (!ValidateVertexShaderAttributeTypeMatch(context))
2804 {
2805 return false;
2806 }
2807
Geoff Lange0cff192017-05-30 13:04:56 -04002808 // Detect that the color buffer types match the fragment shader output types
2809 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2810 {
2811 return false;
2812 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002813 }
2814
Jamie Madill9fdaa492018-02-16 10:52:11 -05002815 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002816}
2817
Jamie Madill5b772312018-03-08 20:28:32 -05002818bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002819 GLenum mode,
2820 GLint first,
2821 GLsizei count,
2822 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002823{
Jamie Madillfd716582014-06-06 17:09:04 -04002824 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002825 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002826 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002827 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002828 }
2829
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002830 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002831 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002832 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002833 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002834 {
James Darpinian30b604d2018-03-12 17:26:57 -07002835 if (curTransformFeedback->getPrimitiveMode() != mode)
2836 {
2837 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2838 // that does not match the current transform feedback object's draw mode (if transform
2839 // feedback
2840 // is active), (3.0.2, section 2.14, pg 86)
2841 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2842 return false;
2843 }
2844
2845 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2846 {
2847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2848 return false;
2849 }
Jamie Madillfd716582014-06-06 17:09:04 -04002850 }
2851
Jiajia Qind9671222016-11-29 16:30:31 +08002852 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002853 {
2854 return false;
2855 }
2856
Corentin Wallez71168a02016-12-19 15:11:18 -08002857 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002858 // - first < 0 has been checked as an error condition.
2859 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002860 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002861 ASSERT(first >= 0);
2862 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002863 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002864 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2865 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2866 {
2867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2868 return false;
2869 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002870
Jamie Madill9fdaa492018-02-16 10:52:11 -05002871 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2872 {
2873 return false;
2874 }
Jamie Madillfd716582014-06-06 17:09:04 -04002875 }
2876
2877 return true;
2878}
2879
He Yunchaoced53ae2016-11-29 15:00:51 +08002880bool ValidateDrawArraysInstancedANGLE(Context *context,
2881 GLenum mode,
2882 GLint first,
2883 GLsizei count,
2884 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002885{
Geoff Lang63c5a592017-09-27 14:08:16 -04002886 if (!context->getExtensions().instancedArrays)
2887 {
2888 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2889 return false;
2890 }
2891
Corentin Wallez170efbf2017-05-02 13:45:01 -04002892 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002893 {
2894 return false;
2895 }
2896
Corentin Wallez0dc97812017-06-22 14:38:44 -04002897 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002898}
2899
Jamie Madill5b772312018-03-08 20:28:32 -05002900bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002901{
Jamie Madill250d33f2014-06-06 17:09:03 -04002902 switch (type)
2903 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002904 case GL_UNSIGNED_BYTE:
2905 case GL_UNSIGNED_SHORT:
2906 break;
2907 case GL_UNSIGNED_INT:
2908 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2909 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002910 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002911 return false;
2912 }
2913 break;
2914 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002916 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002917 }
2918
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002919 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002920
2921 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002922 if (curTransformFeedback && curTransformFeedback->isActive() &&
2923 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002924 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002925 // It is an invalid operation to call DrawElements, DrawRangeElements or
2926 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002927 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002928 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002929 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002930 }
2931
Jiajia Qind9671222016-11-29 16:30:31 +08002932 return true;
2933}
2934
Jamie Madill5b772312018-03-08 20:28:32 -05002935bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002936 GLenum mode,
2937 GLsizei count,
2938 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002939 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002940 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002941{
2942 if (!ValidateDrawElementsBase(context, type))
2943 return false;
2944
2945 const State &state = context->getGLState();
2946
Corentin Wallez170efbf2017-05-02 13:45:01 -04002947 if (!ValidateDrawBase(context, mode, count))
2948 {
2949 return false;
2950 }
2951
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002952 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2953 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2954 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2955 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002956 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002957 // Check for mapped buffers
2958 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002959 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002960 {
2961 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2962 return false;
2963 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002964 }
2965
He Yunchaoced53ae2016-11-29 15:00:51 +08002966 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002967 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002968
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002969 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2970
2971 if (context->getExtensions().webglCompatibility)
2972 {
2973 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2974 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2975 {
2976 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2977 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2978 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002979 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002980 return false;
2981 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002982
2983 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2984 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2985 // error is generated.
2986 if (reinterpret_cast<intptr_t>(indices) < 0)
2987 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002988 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002989 return false;
2990 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002991 }
2992
2993 if (context->getExtensions().webglCompatibility ||
2994 !context->getGLState().areClientArraysEnabled())
2995 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002996 if (!elementArrayBuffer && count > 0)
2997 {
2998 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2999 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3000 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003001 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003002 return false;
3003 }
3004 }
3005
Jamie Madill9fdaa492018-02-16 10:52:11 -05003006 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003007 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003008 // This is an application error that would normally result in a crash, but we catch it and
3009 // return an error
3010 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3011 return false;
3012 }
3013
3014 if (count > 0 && elementArrayBuffer)
3015 {
3016 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3017 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3018 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3019 constexpr uint64_t kMaxTypeSize = 8;
3020 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3021 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3022 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3023
3024 uint64_t typeSize = typeBytes;
3025 uint64_t elementCount = static_cast<uint64_t>(count);
3026 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3027
3028 // Doing the multiplication here is overflow-safe
3029 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3030
3031 // The offset can be any value, check for overflows
3032 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3033 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003034 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003035 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3036 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003037 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003038
3039 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3040 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003041 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003042 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3043 return false;
3044 }
3045
3046 ASSERT(isPow2(typeSize) && typeSize > 0);
3047 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3048 {
3049 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003050 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003051 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003052
3053 if (context->getExtensions().webglCompatibility &&
3054 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3055 {
3056 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3057 ElementArrayBufferBoundForTransformFeedback);
3058 return false;
3059 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003060 }
3061
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003062 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003063 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003064 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3065 // access is enabled.
3066 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3067 {
3068 return false;
3069 }
3070 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003071 else if (count == 0)
3072 {
3073 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3074 // count.
3075 if (!ValidateDrawAttribs(context, 0, 0, 0))
3076 {
3077 return false;
3078 }
3079 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003080 else
3081 {
3082 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003083 const DrawCallParams &params = context->getParams<DrawCallParams>();
3084 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3085 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003086
3087 // If we use an index greater than our maximum supported index range, return an error.
3088 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3089 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003090 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003091 {
3092 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3093 return false;
3094 }
3095
Jamie Madill6f5444d2018-03-14 10:08:11 -04003096 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3097 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003098 {
3099 return false;
3100 }
3101
3102 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003103 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003104 }
3105
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003106 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003107}
3108
Jamie Madill5b772312018-03-08 20:28:32 -05003109bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003110 GLenum mode,
3111 GLsizei count,
3112 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003113 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003114 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003115{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003116 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003117}
3118
Geoff Lang3edfe032015-09-04 16:38:24 -04003119bool ValidateDrawElementsInstancedANGLE(Context *context,
3120 GLenum mode,
3121 GLsizei count,
3122 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003123 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003124 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003125{
Geoff Lang63c5a592017-09-27 14:08:16 -04003126 if (!context->getExtensions().instancedArrays)
3127 {
3128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3129 return false;
3130 }
3131
Corentin Wallez170efbf2017-05-02 13:45:01 -04003132 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003133 {
3134 return false;
3135 }
3136
Corentin Wallez0dc97812017-06-22 14:38:44 -04003137 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003138}
3139
He Yunchaoced53ae2016-11-29 15:00:51 +08003140bool ValidateFramebufferTextureBase(Context *context,
3141 GLenum target,
3142 GLenum attachment,
3143 GLuint texture,
3144 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003145{
Geoff Lange8afa902017-09-27 15:00:43 -04003146 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003149 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003150 }
3151
3152 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003153 {
3154 return false;
3155 }
3156
Jamie Madill55ec3b12014-07-03 10:38:57 -04003157 if (texture != 0)
3158 {
3159 gl::Texture *tex = context->getTexture(texture);
3160
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003161 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003163 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003164 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003165 }
3166
3167 if (level < 0)
3168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003169 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003170 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003171 }
3172 }
3173
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003174 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003175 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003176
Jamie Madill84115c92015-04-23 15:00:07 -04003177 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003178 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003180 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003181 }
3182
3183 return true;
3184}
3185
Geoff Langb1196682014-07-23 13:47:29 -04003186bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003187{
3188 if (program == 0)
3189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003190 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003191 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003192 }
3193
Dian Xiang769769a2015-09-09 15:20:08 -07003194 gl::Program *programObject = GetValidProgram(context, program);
3195 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003196 {
3197 return false;
3198 }
3199
Jamie Madill0063c512014-08-25 15:47:53 -04003200 if (!programObject || !programObject->isLinked())
3201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003203 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003204 }
3205
Geoff Lang7dd2e102014-11-10 15:19:26 -05003206 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003208 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003209 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003210 }
3211
Jamie Madill0063c512014-08-25 15:47:53 -04003212 return true;
3213}
3214
Geoff Langf41d0ee2016-10-07 13:04:23 -04003215static bool ValidateSizedGetUniform(Context *context,
3216 GLuint program,
3217 GLint location,
3218 GLsizei bufSize,
3219 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003220{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003221 if (length)
3222 {
3223 *length = 0;
3224 }
3225
Jamie Madill78f41802014-08-25 15:47:55 -04003226 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003227 {
Jamie Madill78f41802014-08-25 15:47:55 -04003228 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003229 }
3230
Geoff Langf41d0ee2016-10-07 13:04:23 -04003231 if (bufSize < 0)
3232 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003233 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003234 return false;
3235 }
3236
Jamie Madilla502c742014-08-28 17:19:13 -04003237 gl::Program *programObject = context->getProgram(program);
3238 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003239
Jamie Madill78f41802014-08-25 15:47:55 -04003240 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003241 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003242 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003243 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003244 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003246 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003247 }
3248
Geoff Langf41d0ee2016-10-07 13:04:23 -04003249 if (length)
3250 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003251 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003252 }
3253
Jamie Madill0063c512014-08-25 15:47:53 -04003254 return true;
3255}
3256
He Yunchaoced53ae2016-11-29 15:00:51 +08003257bool ValidateGetnUniformfvEXT(Context *context,
3258 GLuint program,
3259 GLint location,
3260 GLsizei bufSize,
3261 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003262{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003263 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003264}
3265
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003266bool ValidateGetnUniformfvRobustANGLE(Context *context,
3267 GLuint program,
3268 GLint location,
3269 GLsizei bufSize,
3270 GLsizei *length,
3271 GLfloat *params)
3272{
3273 UNIMPLEMENTED();
3274 return false;
3275}
3276
He Yunchaoced53ae2016-11-29 15:00:51 +08003277bool ValidateGetnUniformivEXT(Context *context,
3278 GLuint program,
3279 GLint location,
3280 GLsizei bufSize,
3281 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003282{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003283 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3284}
3285
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003286bool ValidateGetnUniformivRobustANGLE(Context *context,
3287 GLuint program,
3288 GLint location,
3289 GLsizei bufSize,
3290 GLsizei *length,
3291 GLint *params)
3292{
3293 UNIMPLEMENTED();
3294 return false;
3295}
3296
3297bool ValidateGetnUniformuivRobustANGLE(Context *context,
3298 GLuint program,
3299 GLint location,
3300 GLsizei bufSize,
3301 GLsizei *length,
3302 GLuint *params)
3303{
3304 UNIMPLEMENTED();
3305 return false;
3306}
3307
Geoff Langf41d0ee2016-10-07 13:04:23 -04003308bool ValidateGetUniformfvRobustANGLE(Context *context,
3309 GLuint program,
3310 GLint location,
3311 GLsizei bufSize,
3312 GLsizei *length,
3313 GLfloat *params)
3314{
3315 if (!ValidateRobustEntryPoint(context, bufSize))
3316 {
3317 return false;
3318 }
3319
Brandon Jonesd1049182018-03-28 10:02:20 -07003320 GLsizei writeLength = 0;
3321
Geoff Langf41d0ee2016-10-07 13:04:23 -04003322 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003323 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3324 {
3325 return false;
3326 }
3327
3328 SetRobustLengthParam(length, writeLength);
3329
3330 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003331}
3332
3333bool ValidateGetUniformivRobustANGLE(Context *context,
3334 GLuint program,
3335 GLint location,
3336 GLsizei bufSize,
3337 GLsizei *length,
3338 GLint *params)
3339{
3340 if (!ValidateRobustEntryPoint(context, bufSize))
3341 {
3342 return false;
3343 }
3344
Brandon Jonesd1049182018-03-28 10:02:20 -07003345 GLsizei writeLength = 0;
3346
Geoff Langf41d0ee2016-10-07 13:04:23 -04003347 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003348 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3349 {
3350 return false;
3351 }
3352
3353 SetRobustLengthParam(length, writeLength);
3354
3355 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003356}
3357
3358bool ValidateGetUniformuivRobustANGLE(Context *context,
3359 GLuint program,
3360 GLint location,
3361 GLsizei bufSize,
3362 GLsizei *length,
3363 GLuint *params)
3364{
3365 if (!ValidateRobustEntryPoint(context, bufSize))
3366 {
3367 return false;
3368 }
3369
3370 if (context->getClientMajorVersion() < 3)
3371 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003372 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003373 return false;
3374 }
3375
Brandon Jonesd1049182018-03-28 10:02:20 -07003376 GLsizei writeLength = 0;
3377
Geoff Langf41d0ee2016-10-07 13:04:23 -04003378 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003379 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3380 {
3381 return false;
3382 }
3383
3384 SetRobustLengthParam(length, writeLength);
3385
3386 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003387}
3388
He Yunchaoced53ae2016-11-29 15:00:51 +08003389bool ValidateDiscardFramebufferBase(Context *context,
3390 GLenum target,
3391 GLsizei numAttachments,
3392 const GLenum *attachments,
3393 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003394{
3395 if (numAttachments < 0)
3396 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003397 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003398 return false;
3399 }
3400
3401 for (GLsizei i = 0; i < numAttachments; ++i)
3402 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003403 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003404 {
3405 if (defaultFramebuffer)
3406 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003408 return false;
3409 }
3410
3411 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003413 context->handleError(InvalidOperation() << "Requested color attachment is "
3414 "greater than the maximum supported "
3415 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003416 return false;
3417 }
3418 }
3419 else
3420 {
3421 switch (attachments[i])
3422 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003423 case GL_DEPTH_ATTACHMENT:
3424 case GL_STENCIL_ATTACHMENT:
3425 case GL_DEPTH_STENCIL_ATTACHMENT:
3426 if (defaultFramebuffer)
3427 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003428 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3429 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003430 return false;
3431 }
3432 break;
3433 case GL_COLOR:
3434 case GL_DEPTH:
3435 case GL_STENCIL:
3436 if (!defaultFramebuffer)
3437 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003438 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3439 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003440 return false;
3441 }
3442 break;
3443 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003444 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003445 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003446 }
3447 }
3448 }
3449
3450 return true;
3451}
3452
Austin Kinross6ee1e782015-05-29 17:05:37 -07003453bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3454{
Jamie Madill007530e2017-12-28 14:27:04 -05003455 if (!context->getExtensions().debugMarker)
3456 {
3457 // The debug marker calls should not set error state
3458 // However, it seems reasonable to set an error state if the extension is not enabled
3459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3460 return false;
3461 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003462
Jamie Madill007530e2017-12-28 14:27:04 -05003463 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003464 if (length < 0)
3465 {
3466 return false;
3467 }
3468
3469 if (marker == nullptr)
3470 {
3471 return false;
3472 }
3473
3474 return true;
3475}
3476
3477bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3478{
Jamie Madill007530e2017-12-28 14:27:04 -05003479 if (!context->getExtensions().debugMarker)
3480 {
3481 // The debug marker calls should not set error state
3482 // However, it seems reasonable to set an error state if the extension is not enabled
3483 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3484 return false;
3485 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003486
Jamie Madill007530e2017-12-28 14:27:04 -05003487 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003488 if (length < 0)
3489 {
3490 return false;
3491 }
3492
3493 if (length > 0 && marker == nullptr)
3494 {
3495 return false;
3496 }
3497
3498 return true;
3499}
3500
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003501bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003502{
Geoff Langa8406172015-07-21 16:53:39 -04003503 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003505 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003506 return false;
3507 }
3508
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003509 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003510 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003511 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003512 if (!context->getExtensions().eglImage)
3513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003514 context->handleError(InvalidEnum()
3515 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003516 }
3517 break;
3518
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003519 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003520 if (!context->getExtensions().eglImageExternal)
3521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003522 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3523 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003524 }
Geoff Langa8406172015-07-21 16:53:39 -04003525 break;
3526
3527 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003528 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003529 return false;
3530 }
3531
Jamie Madill007530e2017-12-28 14:27:04 -05003532 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3533
Jamie Madill61e16b42017-06-19 11:13:23 -04003534 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003535 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003537 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003538 return false;
3539 }
3540
Jamie Madill007530e2017-12-28 14:27:04 -05003541 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003543 context->handleError(InvalidOperation()
3544 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003545 return false;
3546 }
3547
Geoff Langca271392017-04-05 12:30:00 -04003548 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003549 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003550 if (!textureCaps.texturable)
3551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003552 context->handleError(InvalidOperation()
3553 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003554 return false;
3555 }
3556
Geoff Langdcab33b2015-07-21 13:03:16 -04003557 return true;
3558}
3559
3560bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003561 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003562 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003563{
Geoff Langa8406172015-07-21 16:53:39 -04003564 if (!context->getExtensions().eglImage)
3565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003566 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003567 return false;
3568 }
3569
3570 switch (target)
3571 {
3572 case GL_RENDERBUFFER:
3573 break;
3574
3575 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003576 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003577 return false;
3578 }
3579
Jamie Madill007530e2017-12-28 14:27:04 -05003580 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3581
Jamie Madill61e16b42017-06-19 11:13:23 -04003582 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003583 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003585 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003586 return false;
3587 }
3588
Geoff Langca271392017-04-05 12:30:00 -04003589 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003590 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003591 if (!textureCaps.renderable)
3592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003593 context->handleError(InvalidOperation()
3594 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003595 return false;
3596 }
3597
Geoff Langdcab33b2015-07-21 13:03:16 -04003598 return true;
3599}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003600
3601bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3602{
Geoff Lang36167ab2015-12-07 10:27:14 -05003603 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003604 {
3605 // The default VAO should always exist
3606 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003607 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003608 return false;
3609 }
3610
3611 return true;
3612}
3613
Geoff Langc5629752015-12-07 16:29:04 -05003614bool ValidateProgramBinaryBase(Context *context,
3615 GLuint program,
3616 GLenum binaryFormat,
3617 const void *binary,
3618 GLint length)
3619{
3620 Program *programObject = GetValidProgram(context, program);
3621 if (programObject == nullptr)
3622 {
3623 return false;
3624 }
3625
3626 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3627 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3628 programBinaryFormats.end())
3629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003630 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003631 return false;
3632 }
3633
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003634 if (context->hasActiveTransformFeedback(program))
3635 {
3636 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003637 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3638 "is associated with an active transform "
3639 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003640 return false;
3641 }
3642
Geoff Langc5629752015-12-07 16:29:04 -05003643 return true;
3644}
3645
3646bool ValidateGetProgramBinaryBase(Context *context,
3647 GLuint program,
3648 GLsizei bufSize,
3649 GLsizei *length,
3650 GLenum *binaryFormat,
3651 void *binary)
3652{
3653 Program *programObject = GetValidProgram(context, program);
3654 if (programObject == nullptr)
3655 {
3656 return false;
3657 }
3658
3659 if (!programObject->isLinked())
3660 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003661 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003662 return false;
3663 }
3664
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003665 if (context->getCaps().programBinaryFormats.empty())
3666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003667 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003668 return false;
3669 }
3670
Geoff Langc5629752015-12-07 16:29:04 -05003671 return true;
3672}
Jamie Madillc29968b2016-01-20 11:17:23 -05003673
Jamie Madill5b772312018-03-08 20:28:32 -05003674bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003675{
3676 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003677 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003678 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003679 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3680 return false;
3681 }
3682 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3683 {
3684 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003685 return false;
3686 }
3687
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003688 ASSERT(context->getGLState().getDrawFramebuffer());
3689 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003690 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3691
3692 // This should come first before the check for the default frame buffer
3693 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3694 // rather than INVALID_OPERATION
3695 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3696 {
3697 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3698
3699 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003700 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3701 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003702 {
3703 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003704 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3705 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3706 // 3.1 is still a bit ambiguous about the error, but future specs are
3707 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003708 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003709 return false;
3710 }
3711 else if (bufs[colorAttachment] >= maxColorAttachment)
3712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003713 context->handleError(InvalidOperation()
3714 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003715 return false;
3716 }
3717 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3718 frameBufferId != 0)
3719 {
3720 // INVALID_OPERATION-GL is bound to buffer and ith argument
3721 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003722 context->handleError(InvalidOperation()
3723 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003724 return false;
3725 }
3726 }
3727
3728 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3729 // and n is not 1 or bufs is bound to value other than BACK and NONE
3730 if (frameBufferId == 0)
3731 {
3732 if (n != 1)
3733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003734 context->handleError(InvalidOperation()
3735 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003736 return false;
3737 }
3738
3739 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3740 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003741 context->handleError(
3742 InvalidOperation()
3743 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003744 return false;
3745 }
3746 }
3747
3748 return true;
3749}
3750
Geoff Lang496c02d2016-10-20 11:38:11 -07003751bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003752 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003753 GLenum pname,
3754 GLsizei *length,
3755 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003756{
Geoff Lang496c02d2016-10-20 11:38:11 -07003757 if (length)
3758 {
3759 *length = 0;
3760 }
3761
3762 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3763 {
3764 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003765 InvalidOperation()
3766 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003767 return false;
3768 }
3769
Corentin Walleze4477002017-12-01 14:39:58 -05003770 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003771 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003772 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003773 return false;
3774 }
3775
Geoff Lang496c02d2016-10-20 11:38:11 -07003776 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003777 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003778 case GL_BUFFER_MAP_POINTER:
3779 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003780
Geoff Lang496c02d2016-10-20 11:38:11 -07003781 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003782 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003783 return false;
3784 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003785
3786 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3787 // target bound to zero generate an INVALID_OPERATION error."
3788 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003789 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003791 context->handleError(InvalidOperation()
3792 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003793 return false;
3794 }
3795
Geoff Lang496c02d2016-10-20 11:38:11 -07003796 if (length)
3797 {
3798 *length = 1;
3799 }
3800
Olli Etuaho4f667482016-03-30 15:56:35 +03003801 return true;
3802}
3803
Corentin Wallez336129f2017-10-17 15:55:40 -04003804bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003805{
Corentin Walleze4477002017-12-01 14:39:58 -05003806 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003807 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003808 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003809 return false;
3810 }
3811
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003812 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003813
3814 if (buffer == nullptr || !buffer->isMapped())
3815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003816 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003817 return false;
3818 }
3819
3820 return true;
3821}
3822
3823bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003824 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003825 GLintptr offset,
3826 GLsizeiptr length,
3827 GLbitfield access)
3828{
Corentin Walleze4477002017-12-01 14:39:58 -05003829 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003830 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003831 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003832 return false;
3833 }
3834
Brandon Jones6cad5662017-06-14 13:25:13 -07003835 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003836 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003837 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3838 return false;
3839 }
3840
3841 if (length < 0)
3842 {
3843 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003844 return false;
3845 }
3846
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003847 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003848
3849 if (!buffer)
3850 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003851 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003852 return false;
3853 }
3854
3855 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003856 CheckedNumeric<size_t> checkedOffset(offset);
3857 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003858
Jamie Madille2e406c2016-06-02 13:04:10 -04003859 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003861 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003862 return false;
3863 }
3864
3865 // Check for invalid bits in the mask
3866 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3867 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3868 GL_MAP_UNSYNCHRONIZED_BIT;
3869
3870 if (access & ~(allAccessBits))
3871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003872 context->handleError(InvalidValue()
3873 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003874 return false;
3875 }
3876
3877 if (length == 0)
3878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003879 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003880 return false;
3881 }
3882
3883 if (buffer->isMapped())
3884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003885 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003886 return false;
3887 }
3888
3889 // Check for invalid bit combinations
3890 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003892 context->handleError(InvalidOperation()
3893 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003894 return false;
3895 }
3896
3897 GLbitfield writeOnlyBits =
3898 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3899
3900 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003902 context->handleError(InvalidOperation()
3903 << "Invalid access bits when mapping buffer for reading: 0x"
3904 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003905 return false;
3906 }
3907
3908 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003910 context->handleError(
3911 InvalidOperation()
3912 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003913 return false;
3914 }
Geoff Lang79f71042017-08-14 16:43:43 -04003915
3916 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003917}
3918
3919bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003920 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003921 GLintptr offset,
3922 GLsizeiptr length)
3923{
Brandon Jones6cad5662017-06-14 13:25:13 -07003924 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003925 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003926 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3927 return false;
3928 }
3929
3930 if (length < 0)
3931 {
3932 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003933 return false;
3934 }
3935
Corentin Walleze4477002017-12-01 14:39:58 -05003936 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003937 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003938 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003939 return false;
3940 }
3941
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003942 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003943
3944 if (buffer == nullptr)
3945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003946 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003947 return false;
3948 }
3949
3950 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003952 context->handleError(InvalidOperation()
3953 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003954 return false;
3955 }
3956
3957 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003958 CheckedNumeric<size_t> checkedOffset(offset);
3959 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003960
Jamie Madille2e406c2016-06-02 13:04:10 -04003961 if (!checkedSize.IsValid() ||
3962 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003964 context->handleError(InvalidValue()
3965 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003966 return false;
3967 }
3968
3969 return true;
3970}
3971
Olli Etuaho41997e72016-03-10 13:38:39 +02003972bool ValidateGenOrDelete(Context *context, GLint n)
3973{
3974 if (n < 0)
3975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003976 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003977 return false;
3978 }
3979 return true;
3980}
3981
Jamie Madill5b772312018-03-08 20:28:32 -05003982bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003983{
3984 if (!context->getExtensions().robustClientMemory)
3985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003986 context->handleError(InvalidOperation()
3987 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003988 return false;
3989 }
3990
3991 if (bufSize < 0)
3992 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003993 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003994 return false;
3995 }
3996
3997 return true;
3998}
3999
Jamie Madill5b772312018-03-08 20:28:32 -05004000bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004001{
4002 if (bufSize < numParams)
4003 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004004 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4005 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004006 return false;
4007 }
4008
4009 return true;
4010}
4011
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004012bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004013 GLenum target,
4014 GLenum attachment,
4015 GLenum pname,
4016 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004017{
Geoff Lange8afa902017-09-27 15:00:43 -04004018 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004020 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004021 return false;
4022 }
4023
4024 int clientVersion = context->getClientMajorVersion();
4025
4026 switch (pname)
4027 {
4028 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4029 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4030 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4031 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4032 break;
4033
Martin Radeve5285d22017-07-14 16:23:53 +03004034 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4035 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4036 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4037 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4038 if (clientVersion < 3 || !context->getExtensions().multiview)
4039 {
4040 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4041 return false;
4042 }
4043 break;
4044
Geoff Langff5b2d52016-09-07 11:32:23 -04004045 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4046 if (clientVersion < 3 && !context->getExtensions().sRGB)
4047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004048 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004049 return false;
4050 }
4051 break;
4052
4053 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4054 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4055 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4056 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4057 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4058 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4059 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4060 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4061 if (clientVersion < 3)
4062 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004063 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004064 return false;
4065 }
4066 break;
4067
4068 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004069 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004070 return false;
4071 }
4072
4073 // Determine if the attachment is a valid enum
4074 switch (attachment)
4075 {
4076 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 case GL_DEPTH:
4078 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004079 if (clientVersion < 3)
4080 {
Geoff Langfa125c92017-10-24 13:01:46 -04004081 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004082 return false;
4083 }
4084 break;
4085
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004086 case GL_DEPTH_STENCIL_ATTACHMENT:
4087 if (clientVersion < 3 && !context->isWebGL1())
4088 {
4089 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4090 return false;
4091 }
4092 break;
4093
Geoff Langfa125c92017-10-24 13:01:46 -04004094 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004095 case GL_DEPTH_ATTACHMENT:
4096 case GL_STENCIL_ATTACHMENT:
4097 break;
4098
4099 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004100 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4101 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004102 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4103 {
Geoff Langfa125c92017-10-24 13:01:46 -04004104 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004105 return false;
4106 }
4107 break;
4108 }
4109
4110 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4111 ASSERT(framebuffer);
4112
4113 if (framebuffer->id() == 0)
4114 {
4115 if (clientVersion < 3)
4116 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004118 return false;
4119 }
4120
4121 switch (attachment)
4122 {
4123 case GL_BACK:
4124 case GL_DEPTH:
4125 case GL_STENCIL:
4126 break;
4127
4128 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004130 return false;
4131 }
4132 }
4133 else
4134 {
4135 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4136 {
4137 // Valid attachment query
4138 }
4139 else
4140 {
4141 switch (attachment)
4142 {
4143 case GL_DEPTH_ATTACHMENT:
4144 case GL_STENCIL_ATTACHMENT:
4145 break;
4146
4147 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004148 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004150 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004151 return false;
4152 }
4153 break;
4154
4155 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004157 return false;
4158 }
4159 }
4160 }
4161
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004162 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004163 if (attachmentObject)
4164 {
4165 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4166 attachmentObject->type() == GL_TEXTURE ||
4167 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4168
4169 switch (pname)
4170 {
4171 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4172 if (attachmentObject->type() != GL_RENDERBUFFER &&
4173 attachmentObject->type() != GL_TEXTURE)
4174 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004175 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004176 return false;
4177 }
4178 break;
4179
4180 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4181 if (attachmentObject->type() != GL_TEXTURE)
4182 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004183 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004184 return false;
4185 }
4186 break;
4187
4188 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4189 if (attachmentObject->type() != GL_TEXTURE)
4190 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004191 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004192 return false;
4193 }
4194 break;
4195
4196 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4197 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4198 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004200 return false;
4201 }
4202 break;
4203
4204 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4205 if (attachmentObject->type() != GL_TEXTURE)
4206 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004207 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004208 return false;
4209 }
4210 break;
4211
4212 default:
4213 break;
4214 }
4215 }
4216 else
4217 {
4218 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4219 // is NONE, then querying any other pname will generate INVALID_ENUM.
4220
4221 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4222 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4223 // INVALID_OPERATION for all other pnames
4224
4225 switch (pname)
4226 {
4227 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4228 break;
4229
4230 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4231 if (clientVersion < 3)
4232 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004233 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004234 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004235 return false;
4236 }
4237 break;
4238
4239 default:
4240 if (clientVersion < 3)
4241 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004242 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004243 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004244 return false;
4245 }
4246 else
4247 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004248 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004249 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004250 return false;
4251 }
4252 }
4253 }
4254
Martin Radeve5285d22017-07-14 16:23:53 +03004255 if (numParams)
4256 {
4257 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4258 {
4259 // Only when the viewport offsets are queried we can have a varying number of output
4260 // parameters.
4261 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4262 *numParams = numViews * 2;
4263 }
4264 else
4265 {
4266 // For all other queries we can have only one output parameter.
4267 *numParams = 1;
4268 }
4269 }
4270
Geoff Langff5b2d52016-09-07 11:32:23 -04004271 return true;
4272}
4273
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004274bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004275 GLenum target,
4276 GLenum attachment,
4277 GLenum pname,
4278 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004279 GLsizei *length,
4280 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004281{
4282 if (!ValidateRobustEntryPoint(context, bufSize))
4283 {
4284 return false;
4285 }
4286
Brandon Jonesd1049182018-03-28 10:02:20 -07004287 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004288 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004289 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004290 {
4291 return false;
4292 }
4293
Brandon Jonesd1049182018-03-28 10:02:20 -07004294 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004295 {
4296 return false;
4297 }
4298
Brandon Jonesd1049182018-03-28 10:02:20 -07004299 SetRobustLengthParam(length, numParams);
4300
Geoff Langff5b2d52016-09-07 11:32:23 -04004301 return true;
4302}
4303
Jamie Madill5b772312018-03-08 20:28:32 -05004304bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004305 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004306 GLenum pname,
4307 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004308 GLsizei *length,
4309 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004310{
4311 if (!ValidateRobustEntryPoint(context, bufSize))
4312 {
4313 return false;
4314 }
4315
Brandon Jonesd1049182018-03-28 10:02:20 -07004316 GLsizei numParams = 0;
4317
4318 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004319 {
4320 return false;
4321 }
4322
Brandon Jonesd1049182018-03-28 10:02:20 -07004323 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004324 {
4325 return false;
4326 }
4327
Brandon Jonesd1049182018-03-28 10:02:20 -07004328 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004329 return true;
4330}
4331
Jamie Madill5b772312018-03-08 20:28:32 -05004332bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004333 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004334 GLenum pname,
4335 GLsizei bufSize,
4336 GLsizei *length,
4337 GLint64 *params)
4338{
Brandon Jonesd1049182018-03-28 10:02:20 -07004339 GLsizei numParams = 0;
4340
Geoff Langebebe1c2016-10-14 12:01:31 -04004341 if (!ValidateRobustEntryPoint(context, bufSize))
4342 {
4343 return false;
4344 }
4345
Brandon Jonesd1049182018-03-28 10:02:20 -07004346 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004347 {
4348 return false;
4349 }
4350
Brandon Jonesd1049182018-03-28 10:02:20 -07004351 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004352 {
4353 return false;
4354 }
4355
Brandon Jonesd1049182018-03-28 10:02:20 -07004356 SetRobustLengthParam(length, numParams);
4357
Geoff Langff5b2d52016-09-07 11:32:23 -04004358 return true;
4359}
4360
Jamie Madill5b772312018-03-08 20:28:32 -05004361bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004362{
4363 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004364 if (numParams)
4365 {
4366 *numParams = 1;
4367 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004368
4369 Program *programObject = GetValidProgram(context, program);
4370 if (!programObject)
4371 {
4372 return false;
4373 }
4374
4375 switch (pname)
4376 {
4377 case GL_DELETE_STATUS:
4378 case GL_LINK_STATUS:
4379 case GL_VALIDATE_STATUS:
4380 case GL_INFO_LOG_LENGTH:
4381 case GL_ATTACHED_SHADERS:
4382 case GL_ACTIVE_ATTRIBUTES:
4383 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4384 case GL_ACTIVE_UNIFORMS:
4385 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4386 break;
4387
4388 case GL_PROGRAM_BINARY_LENGTH:
4389 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004391 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4392 "requires GL_OES_get_program_binary or "
4393 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004394 return false;
4395 }
4396 break;
4397
4398 case GL_ACTIVE_UNIFORM_BLOCKS:
4399 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4400 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4401 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4402 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4403 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4404 if (context->getClientMajorVersion() < 3)
4405 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004406 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004407 return false;
4408 }
4409 break;
4410
Yunchao He61afff12017-03-14 15:34:03 +08004411 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004412 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004413 if (context->getClientVersion() < Version(3, 1))
4414 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004415 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004416 return false;
4417 }
4418 break;
4419
Jiawei Shao6ae51612018-02-23 14:03:25 +08004420 case GL_COMPUTE_WORK_GROUP_SIZE:
4421 if (context->getClientVersion() < Version(3, 1))
4422 {
4423 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4424 return false;
4425 }
4426
4427 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4428 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4429 // program which has not been linked successfully, or which does not contain objects to
4430 // form a compute shader.
4431 if (!programObject->isLinked())
4432 {
4433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4434 return false;
4435 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004436 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004437 {
4438 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4439 return false;
4440 }
4441 break;
4442
Jiawei Shao447bfac2018-03-14 14:23:40 +08004443 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4444 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4445 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4446 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4447 if (!context->getExtensions().geometryShader)
4448 {
4449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4450 return false;
4451 }
4452
4453 // [EXT_geometry_shader] Chapter 7.12
4454 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4455 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4456 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4457 // successfully, or which does not contain objects to form a geometry shader.
4458 if (!programObject->isLinked())
4459 {
4460 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4461 return false;
4462 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004463 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004464 {
4465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4466 return false;
4467 }
4468 break;
4469
Geoff Langff5b2d52016-09-07 11:32:23 -04004470 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004472 return false;
4473 }
4474
4475 return true;
4476}
4477
4478bool ValidateGetProgramivRobustANGLE(Context *context,
4479 GLuint program,
4480 GLenum pname,
4481 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004482 GLsizei *length,
4483 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004484{
4485 if (!ValidateRobustEntryPoint(context, bufSize))
4486 {
4487 return false;
4488 }
4489
Brandon Jonesd1049182018-03-28 10:02:20 -07004490 GLsizei numParams = 0;
4491
4492 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004493 {
4494 return false;
4495 }
4496
Brandon Jonesd1049182018-03-28 10:02:20 -07004497 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004498 {
4499 return false;
4500 }
4501
Brandon Jonesd1049182018-03-28 10:02:20 -07004502 SetRobustLengthParam(length, numParams);
4503
Geoff Langff5b2d52016-09-07 11:32:23 -04004504 return true;
4505}
4506
Geoff Lang740d9022016-10-07 11:20:52 -04004507bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4508 GLenum target,
4509 GLenum pname,
4510 GLsizei bufSize,
4511 GLsizei *length,
4512 GLint *params)
4513{
4514 if (!ValidateRobustEntryPoint(context, bufSize))
4515 {
4516 return false;
4517 }
4518
Brandon Jonesd1049182018-03-28 10:02:20 -07004519 GLsizei numParams = 0;
4520
4521 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004522 {
4523 return false;
4524 }
4525
Brandon Jonesd1049182018-03-28 10:02:20 -07004526 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004527 {
4528 return false;
4529 }
4530
Brandon Jonesd1049182018-03-28 10:02:20 -07004531 SetRobustLengthParam(length, numParams);
4532
Geoff Lang740d9022016-10-07 11:20:52 -04004533 return true;
4534}
4535
Geoff Langd7d0ed32016-10-07 11:33:51 -04004536bool ValidateGetShaderivRobustANGLE(Context *context,
4537 GLuint shader,
4538 GLenum pname,
4539 GLsizei bufSize,
4540 GLsizei *length,
4541 GLint *params)
4542{
4543 if (!ValidateRobustEntryPoint(context, bufSize))
4544 {
4545 return false;
4546 }
4547
Brandon Jonesd1049182018-03-28 10:02:20 -07004548 GLsizei numParams = 0;
4549
4550 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004551 {
4552 return false;
4553 }
4554
Brandon Jonesd1049182018-03-28 10:02:20 -07004555 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004556 {
4557 return false;
4558 }
4559
Brandon Jonesd1049182018-03-28 10:02:20 -07004560 SetRobustLengthParam(length, numParams);
4561
Geoff Langd7d0ed32016-10-07 11:33:51 -04004562 return true;
4563}
4564
Geoff Langc1984ed2016-10-07 12:41:00 -04004565bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004566 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004567 GLenum pname,
4568 GLsizei bufSize,
4569 GLsizei *length,
4570 GLfloat *params)
4571{
4572 if (!ValidateRobustEntryPoint(context, bufSize))
4573 {
4574 return false;
4575 }
4576
Brandon Jonesd1049182018-03-28 10:02:20 -07004577 GLsizei numParams = 0;
4578
4579 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004580 {
4581 return false;
4582 }
4583
Brandon Jonesd1049182018-03-28 10:02:20 -07004584 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004585 {
4586 return false;
4587 }
4588
Brandon Jonesd1049182018-03-28 10:02:20 -07004589 SetRobustLengthParam(length, numParams);
4590
Geoff Langc1984ed2016-10-07 12:41:00 -04004591 return true;
4592}
4593
Geoff Langc1984ed2016-10-07 12:41:00 -04004594bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004595 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004596 GLenum pname,
4597 GLsizei bufSize,
4598 GLsizei *length,
4599 GLint *params)
4600{
Brandon Jonesd1049182018-03-28 10:02:20 -07004601
Geoff Langc1984ed2016-10-07 12:41:00 -04004602 if (!ValidateRobustEntryPoint(context, bufSize))
4603 {
4604 return false;
4605 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004606 GLsizei numParams = 0;
4607 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004608 {
4609 return false;
4610 }
4611
Brandon Jonesd1049182018-03-28 10:02:20 -07004612 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004613 {
4614 return false;
4615 }
4616
Brandon Jonesd1049182018-03-28 10:02:20 -07004617 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004618 return true;
4619}
4620
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004621bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4622 TextureType target,
4623 GLenum pname,
4624 GLsizei bufSize,
4625 GLsizei *length,
4626 GLint *params)
4627{
4628 UNIMPLEMENTED();
4629 return false;
4630}
4631
4632bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4633 TextureType target,
4634 GLenum pname,
4635 GLsizei bufSize,
4636 GLsizei *length,
4637 GLuint *params)
4638{
4639 UNIMPLEMENTED();
4640 return false;
4641}
4642
Geoff Langc1984ed2016-10-07 12:41:00 -04004643bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004644 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004645 GLenum pname,
4646 GLsizei bufSize,
4647 const GLfloat *params)
4648{
4649 if (!ValidateRobustEntryPoint(context, bufSize))
4650 {
4651 return false;
4652 }
4653
4654 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4655}
4656
Geoff Langc1984ed2016-10-07 12:41:00 -04004657bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004658 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004659 GLenum pname,
4660 GLsizei bufSize,
4661 const GLint *params)
4662{
4663 if (!ValidateRobustEntryPoint(context, bufSize))
4664 {
4665 return false;
4666 }
4667
4668 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4669}
4670
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004671bool ValidateTexParameterIivRobustANGLE(Context *context,
4672 TextureType target,
4673 GLenum pname,
4674 GLsizei bufSize,
4675 const GLint *params)
4676{
4677 UNIMPLEMENTED();
4678 return false;
4679}
4680
4681bool ValidateTexParameterIuivRobustANGLE(Context *context,
4682 TextureType target,
4683 GLenum pname,
4684 GLsizei bufSize,
4685 const GLuint *params)
4686{
4687 UNIMPLEMENTED();
4688 return false;
4689}
4690
Geoff Langc1984ed2016-10-07 12:41:00 -04004691bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4692 GLuint sampler,
4693 GLenum pname,
4694 GLuint bufSize,
4695 GLsizei *length,
4696 GLfloat *params)
4697{
4698 if (!ValidateRobustEntryPoint(context, bufSize))
4699 {
4700 return false;
4701 }
4702
Brandon Jonesd1049182018-03-28 10:02:20 -07004703 GLsizei numParams = 0;
4704
4705 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004706 {
4707 return false;
4708 }
4709
Brandon Jonesd1049182018-03-28 10:02:20 -07004710 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004711 {
4712 return false;
4713 }
4714
Brandon Jonesd1049182018-03-28 10:02:20 -07004715 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004716 return true;
4717}
4718
Geoff Langc1984ed2016-10-07 12:41:00 -04004719bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4720 GLuint sampler,
4721 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004722 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004723 GLsizei *length,
4724 GLint *params)
4725{
4726 if (!ValidateRobustEntryPoint(context, bufSize))
4727 {
4728 return false;
4729 }
4730
Brandon Jonesd1049182018-03-28 10:02:20 -07004731 GLsizei numParams = 0;
4732
4733 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004734 {
4735 return false;
4736 }
4737
Brandon Jonesd1049182018-03-28 10:02:20 -07004738 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004739 {
4740 return false;
4741 }
4742
Brandon Jonesd1049182018-03-28 10:02:20 -07004743 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004744 return true;
4745}
4746
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004747bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4748 GLuint sampler,
4749 GLenum pname,
4750 GLsizei bufSize,
4751 GLsizei *length,
4752 GLint *params)
4753{
4754 UNIMPLEMENTED();
4755 return false;
4756}
4757
4758bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4759 GLuint sampler,
4760 GLenum pname,
4761 GLsizei bufSize,
4762 GLsizei *length,
4763 GLuint *params)
4764{
4765 UNIMPLEMENTED();
4766 return false;
4767}
4768
Geoff Langc1984ed2016-10-07 12:41:00 -04004769bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4770 GLuint sampler,
4771 GLenum pname,
4772 GLsizei bufSize,
4773 const GLfloat *params)
4774{
4775 if (!ValidateRobustEntryPoint(context, bufSize))
4776 {
4777 return false;
4778 }
4779
4780 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4781}
4782
Geoff Langc1984ed2016-10-07 12:41:00 -04004783bool ValidateSamplerParameterivRobustANGLE(Context *context,
4784 GLuint sampler,
4785 GLenum pname,
4786 GLsizei bufSize,
4787 const GLint *params)
4788{
4789 if (!ValidateRobustEntryPoint(context, bufSize))
4790 {
4791 return false;
4792 }
4793
4794 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4795}
4796
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004797bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4798 GLuint sampler,
4799 GLenum pname,
4800 GLsizei bufSize,
4801 const GLint *param)
4802{
4803 UNIMPLEMENTED();
4804 return false;
4805}
4806
4807bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4808 GLuint sampler,
4809 GLenum pname,
4810 GLsizei bufSize,
4811 const GLuint *param)
4812{
4813 UNIMPLEMENTED();
4814 return false;
4815}
4816
Geoff Lang0b031062016-10-13 14:30:04 -04004817bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4818 GLuint index,
4819 GLenum pname,
4820 GLsizei bufSize,
4821 GLsizei *length,
4822 GLfloat *params)
4823{
4824 if (!ValidateRobustEntryPoint(context, bufSize))
4825 {
4826 return false;
4827 }
4828
Brandon Jonesd1049182018-03-28 10:02:20 -07004829 GLsizei writeLength = 0;
4830
4831 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004832 {
4833 return false;
4834 }
4835
Brandon Jonesd1049182018-03-28 10:02:20 -07004836 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004837 {
4838 return false;
4839 }
4840
Brandon Jonesd1049182018-03-28 10:02:20 -07004841 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004842 return true;
4843}
4844
Geoff Lang0b031062016-10-13 14:30:04 -04004845bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4846 GLuint index,
4847 GLenum pname,
4848 GLsizei bufSize,
4849 GLsizei *length,
4850 GLint *params)
4851{
4852 if (!ValidateRobustEntryPoint(context, bufSize))
4853 {
4854 return false;
4855 }
4856
Brandon Jonesd1049182018-03-28 10:02:20 -07004857 GLsizei writeLength = 0;
4858
4859 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004860 {
4861 return false;
4862 }
4863
Brandon Jonesd1049182018-03-28 10:02:20 -07004864 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004865 {
4866 return false;
4867 }
4868
Brandon Jonesd1049182018-03-28 10:02:20 -07004869 SetRobustLengthParam(length, writeLength);
4870
Geoff Lang0b031062016-10-13 14:30:04 -04004871 return true;
4872}
4873
Geoff Lang0b031062016-10-13 14:30:04 -04004874bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4875 GLuint index,
4876 GLenum pname,
4877 GLsizei bufSize,
4878 GLsizei *length,
4879 void **pointer)
4880{
4881 if (!ValidateRobustEntryPoint(context, bufSize))
4882 {
4883 return false;
4884 }
4885
Brandon Jonesd1049182018-03-28 10:02:20 -07004886 GLsizei writeLength = 0;
4887
4888 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004889 {
4890 return false;
4891 }
4892
Brandon Jonesd1049182018-03-28 10:02:20 -07004893 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004894 {
4895 return false;
4896 }
4897
Brandon Jonesd1049182018-03-28 10:02:20 -07004898 SetRobustLengthParam(length, writeLength);
4899
Geoff Lang0b031062016-10-13 14:30:04 -04004900 return true;
4901}
4902
Geoff Lang0b031062016-10-13 14:30:04 -04004903bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4904 GLuint index,
4905 GLenum pname,
4906 GLsizei bufSize,
4907 GLsizei *length,
4908 GLint *params)
4909{
4910 if (!ValidateRobustEntryPoint(context, bufSize))
4911 {
4912 return false;
4913 }
4914
Brandon Jonesd1049182018-03-28 10:02:20 -07004915 GLsizei writeLength = 0;
4916
4917 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004918 {
4919 return false;
4920 }
4921
Brandon Jonesd1049182018-03-28 10:02:20 -07004922 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004923 {
4924 return false;
4925 }
4926
Brandon Jonesd1049182018-03-28 10:02:20 -07004927 SetRobustLengthParam(length, writeLength);
4928
Geoff Lang0b031062016-10-13 14:30:04 -04004929 return true;
4930}
4931
Geoff Lang0b031062016-10-13 14:30:04 -04004932bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4933 GLuint index,
4934 GLenum pname,
4935 GLsizei bufSize,
4936 GLsizei *length,
4937 GLuint *params)
4938{
4939 if (!ValidateRobustEntryPoint(context, bufSize))
4940 {
4941 return false;
4942 }
4943
Brandon Jonesd1049182018-03-28 10:02:20 -07004944 GLsizei writeLength = 0;
4945
4946 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004947 {
4948 return false;
4949 }
4950
Brandon Jonesd1049182018-03-28 10:02:20 -07004951 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004952 {
4953 return false;
4954 }
4955
Brandon Jonesd1049182018-03-28 10:02:20 -07004956 SetRobustLengthParam(length, writeLength);
4957
Geoff Lang0b031062016-10-13 14:30:04 -04004958 return true;
4959}
4960
Geoff Lang6899b872016-10-14 11:30:13 -04004961bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4962 GLuint program,
4963 GLuint uniformBlockIndex,
4964 GLenum pname,
4965 GLsizei bufSize,
4966 GLsizei *length,
4967 GLint *params)
4968{
4969 if (!ValidateRobustEntryPoint(context, bufSize))
4970 {
4971 return false;
4972 }
4973
Brandon Jonesd1049182018-03-28 10:02:20 -07004974 GLsizei writeLength = 0;
4975
4976 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4977 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004978 {
4979 return false;
4980 }
4981
Brandon Jonesd1049182018-03-28 10:02:20 -07004982 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004983 {
4984 return false;
4985 }
4986
Brandon Jonesd1049182018-03-28 10:02:20 -07004987 SetRobustLengthParam(length, writeLength);
4988
Geoff Lang6899b872016-10-14 11:30:13 -04004989 return true;
4990}
4991
Brandon Jones416aaf92018-04-10 08:10:16 -07004992bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004993 GLenum target,
4994 GLenum internalformat,
4995 GLenum pname,
4996 GLsizei bufSize,
4997 GLsizei *length,
4998 GLint *params)
4999{
5000 if (!ValidateRobustEntryPoint(context, bufSize))
5001 {
5002 return false;
5003 }
5004
Brandon Jonesd1049182018-03-28 10:02:20 -07005005 GLsizei numParams = 0;
5006
5007 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5008 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005009 {
5010 return false;
5011 }
5012
Brandon Jonesd1049182018-03-28 10:02:20 -07005013 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005014 {
5015 return false;
5016 }
5017
Brandon Jonesd1049182018-03-28 10:02:20 -07005018 SetRobustLengthParam(length, numParams);
5019
Geoff Lang0a9661f2016-10-20 10:59:20 -07005020 return true;
5021}
5022
Jamie Madill5b772312018-03-08 20:28:32 -05005023bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005024 GLuint attribIndex,
5025 GLint size,
5026 GLenum type,
5027 GLboolean pureInteger)
5028{
5029 const Caps &caps = context->getCaps();
5030 if (attribIndex >= caps.maxVertexAttributes)
5031 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005032 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005033 return false;
5034 }
5035
5036 if (size < 1 || size > 4)
5037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005038 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005039 return false;
Shao80957d92017-02-20 21:25:59 +08005040 }
5041
5042 switch (type)
5043 {
5044 case GL_BYTE:
5045 case GL_UNSIGNED_BYTE:
5046 case GL_SHORT:
5047 case GL_UNSIGNED_SHORT:
5048 break;
5049
5050 case GL_INT:
5051 case GL_UNSIGNED_INT:
5052 if (context->getClientMajorVersion() < 3)
5053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005054 context->handleError(InvalidEnum()
5055 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005056 return false;
5057 }
5058 break;
5059
5060 case GL_FIXED:
5061 case GL_FLOAT:
5062 if (pureInteger)
5063 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005064 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005065 return false;
5066 }
5067 break;
5068
5069 case GL_HALF_FLOAT:
5070 if (context->getClientMajorVersion() < 3)
5071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005072 context->handleError(InvalidEnum()
5073 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005074 return false;
5075 }
5076 if (pureInteger)
5077 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005078 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005079 return false;
5080 }
5081 break;
5082
5083 case GL_INT_2_10_10_10_REV:
5084 case GL_UNSIGNED_INT_2_10_10_10_REV:
5085 if (context->getClientMajorVersion() < 3)
5086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005087 context->handleError(InvalidEnum()
5088 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005089 return false;
5090 }
5091 if (pureInteger)
5092 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005093 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005094 return false;
5095 }
5096 if (size != 4)
5097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005098 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5099 "UNSIGNED_INT_2_10_10_10_REV and "
5100 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005101 return false;
5102 }
5103 break;
5104
5105 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005106 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005107 return false;
5108 }
5109
5110 return true;
5111}
5112
Geoff Lang76e65652017-03-27 14:58:02 -04005113// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5114// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5115// specified clear value and the type of a buffer that is being cleared generates an
5116// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005117bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005118 GLint drawbuffer,
5119 const GLenum *validComponentTypes,
5120 size_t validComponentTypeCount)
5121{
5122 const FramebufferAttachment *attachment =
5123 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5124 if (attachment)
5125 {
5126 GLenum componentType = attachment->getFormat().info->componentType;
5127 const GLenum *end = validComponentTypes + validComponentTypeCount;
5128 if (std::find(validComponentTypes, end, componentType) == end)
5129 {
5130 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005131 InvalidOperation()
5132 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005133 return false;
5134 }
5135 }
5136
5137 return true;
5138}
5139
Jamie Madill5b772312018-03-08 20:28:32 -05005140bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005141{
5142 if (!ValidateRobustEntryPoint(context, dataSize))
5143 {
5144 return false;
5145 }
5146
Corentin Wallez336129f2017-10-17 15:55:40 -04005147 gl::Buffer *pixelUnpackBuffer =
5148 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005149 if (pixelUnpackBuffer == nullptr)
5150 {
5151 if (dataSize < imageSize)
5152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005153 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005154 }
5155 }
5156 return true;
5157}
5158
Jamie Madill5b772312018-03-08 20:28:32 -05005159bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005160 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005161 GLenum pname,
5162 bool pointerVersion,
5163 GLsizei *numParams)
5164{
5165 if (numParams)
5166 {
5167 *numParams = 0;
5168 }
5169
Corentin Walleze4477002017-12-01 14:39:58 -05005170 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005172 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005173 return false;
5174 }
5175
5176 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5177 if (!buffer)
5178 {
5179 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005181 return false;
5182 }
5183
5184 const Extensions &extensions = context->getExtensions();
5185
5186 switch (pname)
5187 {
5188 case GL_BUFFER_USAGE:
5189 case GL_BUFFER_SIZE:
5190 break;
5191
5192 case GL_BUFFER_ACCESS_OES:
5193 if (!extensions.mapBuffer)
5194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005195 context->handleError(InvalidEnum()
5196 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005197 return false;
5198 }
5199 break;
5200
5201 case GL_BUFFER_MAPPED:
5202 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5203 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5204 !extensions.mapBufferRange)
5205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005206 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5207 "GL_OES_mapbuffer or "
5208 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005209 return false;
5210 }
5211 break;
5212
5213 case GL_BUFFER_MAP_POINTER:
5214 if (!pointerVersion)
5215 {
5216 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005217 InvalidEnum()
5218 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005219 return false;
5220 }
5221 break;
5222
5223 case GL_BUFFER_ACCESS_FLAGS:
5224 case GL_BUFFER_MAP_OFFSET:
5225 case GL_BUFFER_MAP_LENGTH:
5226 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005228 context->handleError(InvalidEnum()
5229 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005230 return false;
5231 }
5232 break;
5233
5234 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005235 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005236 return false;
5237 }
5238
5239 // All buffer parameter queries return one value.
5240 if (numParams)
5241 {
5242 *numParams = 1;
5243 }
5244
5245 return true;
5246}
5247
5248bool ValidateGetRenderbufferParameterivBase(Context *context,
5249 GLenum target,
5250 GLenum pname,
5251 GLsizei *length)
5252{
5253 if (length)
5254 {
5255 *length = 0;
5256 }
5257
5258 if (target != GL_RENDERBUFFER)
5259 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005260 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005261 return false;
5262 }
5263
5264 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5265 if (renderbuffer == nullptr)
5266 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005268 return false;
5269 }
5270
5271 switch (pname)
5272 {
5273 case GL_RENDERBUFFER_WIDTH:
5274 case GL_RENDERBUFFER_HEIGHT:
5275 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5276 case GL_RENDERBUFFER_RED_SIZE:
5277 case GL_RENDERBUFFER_GREEN_SIZE:
5278 case GL_RENDERBUFFER_BLUE_SIZE:
5279 case GL_RENDERBUFFER_ALPHA_SIZE:
5280 case GL_RENDERBUFFER_DEPTH_SIZE:
5281 case GL_RENDERBUFFER_STENCIL_SIZE:
5282 break;
5283
5284 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5285 if (!context->getExtensions().framebufferMultisample)
5286 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005287 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005288 return false;
5289 }
5290 break;
5291
5292 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005293 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005294 return false;
5295 }
5296
5297 if (length)
5298 {
5299 *length = 1;
5300 }
5301 return true;
5302}
5303
5304bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5305{
5306 if (length)
5307 {
5308 *length = 0;
5309 }
5310
5311 if (GetValidShader(context, shader) == nullptr)
5312 {
5313 return false;
5314 }
5315
5316 switch (pname)
5317 {
5318 case GL_SHADER_TYPE:
5319 case GL_DELETE_STATUS:
5320 case GL_COMPILE_STATUS:
5321 case GL_INFO_LOG_LENGTH:
5322 case GL_SHADER_SOURCE_LENGTH:
5323 break;
5324
5325 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5326 if (!context->getExtensions().translatedShaderSource)
5327 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005328 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005329 return false;
5330 }
5331 break;
5332
5333 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005334 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005335 return false;
5336 }
5337
5338 if (length)
5339 {
5340 *length = 1;
5341 }
5342 return true;
5343}
5344
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005345bool ValidateGetTexParameterBase(Context *context,
5346 TextureType target,
5347 GLenum pname,
5348 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005349{
5350 if (length)
5351 {
5352 *length = 0;
5353 }
5354
5355 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5356 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005358 return false;
5359 }
5360
5361 if (context->getTargetTexture(target) == nullptr)
5362 {
5363 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005365 return false;
5366 }
5367
5368 switch (pname)
5369 {
5370 case GL_TEXTURE_MAG_FILTER:
5371 case GL_TEXTURE_MIN_FILTER:
5372 case GL_TEXTURE_WRAP_S:
5373 case GL_TEXTURE_WRAP_T:
5374 break;
5375
5376 case GL_TEXTURE_USAGE_ANGLE:
5377 if (!context->getExtensions().textureUsage)
5378 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005379 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005380 return false;
5381 }
5382 break;
5383
5384 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005385 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005387 return false;
5388 }
5389 break;
5390
5391 case GL_TEXTURE_IMMUTABLE_FORMAT:
5392 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5393 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005394 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005395 return false;
5396 }
5397 break;
5398
5399 case GL_TEXTURE_WRAP_R:
5400 case GL_TEXTURE_IMMUTABLE_LEVELS:
5401 case GL_TEXTURE_SWIZZLE_R:
5402 case GL_TEXTURE_SWIZZLE_G:
5403 case GL_TEXTURE_SWIZZLE_B:
5404 case GL_TEXTURE_SWIZZLE_A:
5405 case GL_TEXTURE_BASE_LEVEL:
5406 case GL_TEXTURE_MAX_LEVEL:
5407 case GL_TEXTURE_MIN_LOD:
5408 case GL_TEXTURE_MAX_LOD:
5409 case GL_TEXTURE_COMPARE_MODE:
5410 case GL_TEXTURE_COMPARE_FUNC:
5411 if (context->getClientMajorVersion() < 3)
5412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005413 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005414 return false;
5415 }
5416 break;
5417
5418 case GL_TEXTURE_SRGB_DECODE_EXT:
5419 if (!context->getExtensions().textureSRGBDecode)
5420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005421 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005422 return false;
5423 }
5424 break;
5425
Yunchao Hebacaa712018-01-30 14:01:39 +08005426 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5427 if (context->getClientVersion() < Version(3, 1))
5428 {
5429 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5430 return false;
5431 }
5432 break;
5433
Jamie Madillbe849e42017-05-02 15:49:00 -04005434 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005436 return false;
5437 }
5438
5439 if (length)
5440 {
5441 *length = 1;
5442 }
5443 return true;
5444}
5445
5446bool ValidateGetVertexAttribBase(Context *context,
5447 GLuint index,
5448 GLenum pname,
5449 GLsizei *length,
5450 bool pointer,
5451 bool pureIntegerEntryPoint)
5452{
5453 if (length)
5454 {
5455 *length = 0;
5456 }
5457
5458 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005460 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005461 return false;
5462 }
5463
5464 if (index >= context->getCaps().maxVertexAttributes)
5465 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005466 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 return false;
5468 }
5469
5470 if (pointer)
5471 {
5472 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5473 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005474 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005475 return false;
5476 }
5477 }
5478 else
5479 {
5480 switch (pname)
5481 {
5482 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5483 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5484 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5485 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5486 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5487 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5488 case GL_CURRENT_VERTEX_ATTRIB:
5489 break;
5490
5491 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5492 static_assert(
5493 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5494 "ANGLE extension enums not equal to GL enums.");
5495 if (context->getClientMajorVersion() < 3 &&
5496 !context->getExtensions().instancedArrays)
5497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005498 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5499 "requires OpenGL ES 3.0 or "
5500 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005501 return false;
5502 }
5503 break;
5504
5505 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5506 if (context->getClientMajorVersion() < 3)
5507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005508 context->handleError(
5509 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005510 return false;
5511 }
5512 break;
5513
5514 case GL_VERTEX_ATTRIB_BINDING:
5515 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5516 if (context->getClientVersion() < ES_3_1)
5517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005518 context->handleError(InvalidEnum()
5519 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005520 return false;
5521 }
5522 break;
5523
5524 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005525 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005526 return false;
5527 }
5528 }
5529
5530 if (length)
5531 {
5532 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5533 {
5534 *length = 4;
5535 }
5536 else
5537 {
5538 *length = 1;
5539 }
5540 }
5541
5542 return true;
5543}
5544
Jamie Madill4928b7c2017-06-20 12:57:39 -04005545bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005546 GLint x,
5547 GLint y,
5548 GLsizei width,
5549 GLsizei height,
5550 GLenum format,
5551 GLenum type,
5552 GLsizei bufSize,
5553 GLsizei *length,
5554 GLsizei *columns,
5555 GLsizei *rows,
5556 void *pixels)
5557{
5558 if (length != nullptr)
5559 {
5560 *length = 0;
5561 }
5562 if (rows != nullptr)
5563 {
5564 *rows = 0;
5565 }
5566 if (columns != nullptr)
5567 {
5568 *columns = 0;
5569 }
5570
5571 if (width < 0 || height < 0)
5572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005573 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005574 return false;
5575 }
5576
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005577 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005578
Jamie Madille98b1b52018-03-08 09:47:23 -05005579 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madillbe849e42017-05-02 15:49:00 -04005580 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005581 return false;
5582 }
5583
Jamie Madille98b1b52018-03-08 09:47:23 -05005584 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005585 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 return false;
5587 }
5588
Jamie Madill690c8eb2018-03-12 15:20:03 -04005589 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005590 ASSERT(framebuffer);
5591
5592 if (framebuffer->getReadBufferState() == GL_NONE)
5593 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005594 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005595 return false;
5596 }
5597
5598 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5599 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5600 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5601 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5602 // situation is an application error that would lead to a crash in ANGLE.
5603 if (readBuffer == nullptr)
5604 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005606 return false;
5607 }
5608
Martin Radev28031682017-07-28 14:47:56 +03005609 // ANGLE_multiview, Revision 1:
5610 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5611 // current read framebuffer is not NONE.
5612 if (readBuffer->getMultiviewLayout() != GL_NONE)
5613 {
5614 context->handleError(InvalidFramebufferOperation()
5615 << "Attempting to read from a multi-view framebuffer.");
5616 return false;
5617 }
5618
Geoff Lang280ba992017-04-18 16:30:58 -04005619 if (context->getExtensions().webglCompatibility)
5620 {
5621 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5622 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5623 // and type before validating the combination of format and type. However, the
5624 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5625 // verifies that GL_INVALID_OPERATION is generated.
5626 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5627 // dEQP/WebGL.
5628 if (!ValidReadPixelsFormatEnum(context, format))
5629 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005630 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005631 return false;
5632 }
5633
5634 if (!ValidReadPixelsTypeEnum(context, type))
5635 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005637 return false;
5638 }
5639 }
5640
Jamie Madill690c8eb2018-03-12 15:20:03 -04005641 GLenum currentFormat = GL_NONE;
5642 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5643
5644 GLenum currentType = GL_NONE;
5645 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5646
Jamie Madillbe849e42017-05-02 15:49:00 -04005647 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5648
5649 bool validFormatTypeCombination =
5650 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5651
5652 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5653 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005655 return false;
5656 }
5657
5658 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005659 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5661 {
5662 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005663 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005664 return false;
5665 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005666 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5667 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5668 {
5669 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5670 return false;
5671 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005672
5673 // .. the data would be packed to the buffer object such that the memory writes required
5674 // would exceed the data store size.
5675 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5676 const gl::Extents size(width, height, 1);
5677 const auto &pack = context->getGLState().getPackState();
5678
5679 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5680 if (endByteOrErr.isError())
5681 {
5682 context->handleError(endByteOrErr.getError());
5683 return false;
5684 }
5685
5686 size_t endByte = endByteOrErr.getResult();
5687 if (bufSize >= 0)
5688 {
5689 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5690 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005691 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005692 return false;
5693 }
5694 }
5695
5696 if (pixelPackBuffer != nullptr)
5697 {
5698 CheckedNumeric<size_t> checkedEndByte(endByte);
5699 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5700 checkedEndByte += checkedOffset;
5701
5702 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5703 {
5704 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005706 return false;
5707 }
5708 }
5709
5710 if (pixelPackBuffer == nullptr && length != nullptr)
5711 {
5712 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5713 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005714 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005715 return false;
5716 }
5717
5718 *length = static_cast<GLsizei>(endByte);
5719 }
5720
Geoff Langa953b522018-02-21 16:56:23 -05005721 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005722 angle::CheckedNumeric<int> clippedExtent(length);
5723 if (start < 0)
5724 {
5725 // "subtract" the area that is less than 0
5726 clippedExtent += start;
5727 }
5728
Geoff Langa953b522018-02-21 16:56:23 -05005729 angle::CheckedNumeric<int> readExtent = start;
5730 readExtent += length;
5731 if (!readExtent.IsValid())
5732 {
5733 return false;
5734 }
5735
5736 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005737 {
5738 // Subtract the region to the right of the read buffer
5739 clippedExtent -= (readExtent - bufferSize);
5740 }
5741
5742 if (!clippedExtent.IsValid())
5743 {
Geoff Langa953b522018-02-21 16:56:23 -05005744 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005745 }
5746
Geoff Langa953b522018-02-21 16:56:23 -05005747 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5748 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005749 };
5750
Geoff Langa953b522018-02-21 16:56:23 -05005751 GLsizei writtenColumns = 0;
5752 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5753 {
5754 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5755 return false;
5756 }
5757
5758 GLsizei writtenRows = 0;
5759 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5760 {
5761 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5762 return false;
5763 }
5764
Jamie Madillbe849e42017-05-02 15:49:00 -04005765 if (columns != nullptr)
5766 {
Geoff Langa953b522018-02-21 16:56:23 -05005767 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005768 }
5769
5770 if (rows != nullptr)
5771 {
Geoff Langa953b522018-02-21 16:56:23 -05005772 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005773 }
5774
5775 return true;
5776}
5777
5778template <typename ParamType>
5779bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005780 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005781 GLenum pname,
5782 GLsizei bufSize,
5783 const ParamType *params)
5784{
5785 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5786 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005787 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005788 return false;
5789 }
5790
5791 if (context->getTargetTexture(target) == nullptr)
5792 {
5793 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005794 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005795 return false;
5796 }
5797
5798 const GLsizei minBufSize = 1;
5799 if (bufSize >= 0 && bufSize < minBufSize)
5800 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005801 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005802 return false;
5803 }
5804
5805 switch (pname)
5806 {
5807 case GL_TEXTURE_WRAP_R:
5808 case GL_TEXTURE_SWIZZLE_R:
5809 case GL_TEXTURE_SWIZZLE_G:
5810 case GL_TEXTURE_SWIZZLE_B:
5811 case GL_TEXTURE_SWIZZLE_A:
5812 case GL_TEXTURE_BASE_LEVEL:
5813 case GL_TEXTURE_MAX_LEVEL:
5814 case GL_TEXTURE_COMPARE_MODE:
5815 case GL_TEXTURE_COMPARE_FUNC:
5816 case GL_TEXTURE_MIN_LOD:
5817 case GL_TEXTURE_MAX_LOD:
5818 if (context->getClientMajorVersion() < 3)
5819 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005820 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005821 return false;
5822 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005823 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005825 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5826 "available without "
5827 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005828 return false;
5829 }
5830 break;
5831
5832 default:
5833 break;
5834 }
5835
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005836 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005837 {
5838 switch (pname)
5839 {
5840 case GL_TEXTURE_MIN_FILTER:
5841 case GL_TEXTURE_MAG_FILTER:
5842 case GL_TEXTURE_WRAP_S:
5843 case GL_TEXTURE_WRAP_T:
5844 case GL_TEXTURE_WRAP_R:
5845 case GL_TEXTURE_MIN_LOD:
5846 case GL_TEXTURE_MAX_LOD:
5847 case GL_TEXTURE_COMPARE_MODE:
5848 case GL_TEXTURE_COMPARE_FUNC:
5849 context->handleError(InvalidEnum()
5850 << "Invalid parameter for 2D multisampled textures.");
5851 return false;
5852 }
5853 }
5854
Jamie Madillbe849e42017-05-02 15:49:00 -04005855 switch (pname)
5856 {
5857 case GL_TEXTURE_WRAP_S:
5858 case GL_TEXTURE_WRAP_T:
5859 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005860 {
5861 bool restrictedWrapModes =
5862 target == TextureType::External || target == TextureType::Rectangle;
5863 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005864 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005865 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005866 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005867 }
5868 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005869
5870 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005871 {
5872 bool restrictedMinFilter =
5873 target == TextureType::External || target == TextureType::Rectangle;
5874 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005875 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005876 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005877 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005878 }
5879 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005880
5881 case GL_TEXTURE_MAG_FILTER:
5882 if (!ValidateTextureMagFilterValue(context, params))
5883 {
5884 return false;
5885 }
5886 break;
5887
5888 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005889 if (!context->getExtensions().textureUsage)
5890 {
5891 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5892 return false;
5893 }
5894
Jamie Madillbe849e42017-05-02 15:49:00 -04005895 switch (ConvertToGLenum(params[0]))
5896 {
5897 case GL_NONE:
5898 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5899 break;
5900
5901 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005902 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005903 return false;
5904 }
5905 break;
5906
5907 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005908 {
5909 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5910 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005911 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005912 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005913 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005914 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5915 }
5916 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005917
5918 case GL_TEXTURE_MIN_LOD:
5919 case GL_TEXTURE_MAX_LOD:
5920 // any value is permissible
5921 break;
5922
5923 case GL_TEXTURE_COMPARE_MODE:
5924 if (!ValidateTextureCompareModeValue(context, params))
5925 {
5926 return false;
5927 }
5928 break;
5929
5930 case GL_TEXTURE_COMPARE_FUNC:
5931 if (!ValidateTextureCompareFuncValue(context, params))
5932 {
5933 return false;
5934 }
5935 break;
5936
5937 case GL_TEXTURE_SWIZZLE_R:
5938 case GL_TEXTURE_SWIZZLE_G:
5939 case GL_TEXTURE_SWIZZLE_B:
5940 case GL_TEXTURE_SWIZZLE_A:
5941 switch (ConvertToGLenum(params[0]))
5942 {
5943 case GL_RED:
5944 case GL_GREEN:
5945 case GL_BLUE:
5946 case GL_ALPHA:
5947 case GL_ZERO:
5948 case GL_ONE:
5949 break;
5950
5951 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005952 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005953 return false;
5954 }
5955 break;
5956
5957 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005958 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005960 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005961 return false;
5962 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005963 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005965 context->handleError(InvalidOperation()
5966 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005967 return false;
5968 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005969 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005970 {
5971 context->handleError(InvalidOperation()
5972 << "Base level must be 0 for multisampled textures.");
5973 return false;
5974 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005975 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005976 {
5977 context->handleError(InvalidOperation()
5978 << "Base level must be 0 for rectangle textures.");
5979 return false;
5980 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005981 break;
5982
5983 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005984 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005986 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005987 return false;
5988 }
5989 break;
5990
5991 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5992 if (context->getClientVersion() < Version(3, 1))
5993 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005994 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005995 return false;
5996 }
5997 switch (ConvertToGLenum(params[0]))
5998 {
5999 case GL_DEPTH_COMPONENT:
6000 case GL_STENCIL_INDEX:
6001 break;
6002
6003 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006004 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006005 return false;
6006 }
6007 break;
6008
6009 case GL_TEXTURE_SRGB_DECODE_EXT:
6010 if (!ValidateTextureSRGBDecodeValue(context, params))
6011 {
6012 return false;
6013 }
6014 break;
6015
6016 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006017 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006018 return false;
6019 }
6020
6021 return true;
6022}
6023
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006024template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6025template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006026
Jamie Madill5b772312018-03-08 20:28:32 -05006027bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006028{
6029 if (index >= MAX_VERTEX_ATTRIBS)
6030 {
6031 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6032 return false;
6033 }
6034
6035 return true;
6036}
6037
6038bool ValidateGetActiveUniformBlockivBase(Context *context,
6039 GLuint program,
6040 GLuint uniformBlockIndex,
6041 GLenum pname,
6042 GLsizei *length)
6043{
6044 if (length)
6045 {
6046 *length = 0;
6047 }
6048
6049 if (context->getClientMajorVersion() < 3)
6050 {
6051 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6052 return false;
6053 }
6054
6055 Program *programObject = GetValidProgram(context, program);
6056 if (!programObject)
6057 {
6058 return false;
6059 }
6060
6061 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6062 {
6063 context->handleError(InvalidValue()
6064 << "uniformBlockIndex exceeds active uniform block count.");
6065 return false;
6066 }
6067
6068 switch (pname)
6069 {
6070 case GL_UNIFORM_BLOCK_BINDING:
6071 case GL_UNIFORM_BLOCK_DATA_SIZE:
6072 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6073 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6074 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6075 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6076 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6077 break;
6078
6079 default:
6080 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6081 return false;
6082 }
6083
6084 if (length)
6085 {
6086 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6087 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006088 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006089 programObject->getUniformBlockByIndex(uniformBlockIndex);
6090 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6091 }
6092 else
6093 {
6094 *length = 1;
6095 }
6096 }
6097
6098 return true;
6099}
6100
Jamie Madill9696d072017-08-26 23:19:57 -04006101template <typename ParamType>
6102bool ValidateSamplerParameterBase(Context *context,
6103 GLuint sampler,
6104 GLenum pname,
6105 GLsizei bufSize,
6106 ParamType *params)
6107{
6108 if (context->getClientMajorVersion() < 3)
6109 {
6110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6111 return false;
6112 }
6113
6114 if (!context->isSampler(sampler))
6115 {
6116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6117 return false;
6118 }
6119
6120 const GLsizei minBufSize = 1;
6121 if (bufSize >= 0 && bufSize < minBufSize)
6122 {
6123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6124 return false;
6125 }
6126
6127 switch (pname)
6128 {
6129 case GL_TEXTURE_WRAP_S:
6130 case GL_TEXTURE_WRAP_T:
6131 case GL_TEXTURE_WRAP_R:
6132 if (!ValidateTextureWrapModeValue(context, params, false))
6133 {
6134 return false;
6135 }
6136 break;
6137
6138 case GL_TEXTURE_MIN_FILTER:
6139 if (!ValidateTextureMinFilterValue(context, params, false))
6140 {
6141 return false;
6142 }
6143 break;
6144
6145 case GL_TEXTURE_MAG_FILTER:
6146 if (!ValidateTextureMagFilterValue(context, params))
6147 {
6148 return false;
6149 }
6150 break;
6151
6152 case GL_TEXTURE_MIN_LOD:
6153 case GL_TEXTURE_MAX_LOD:
6154 // any value is permissible
6155 break;
6156
6157 case GL_TEXTURE_COMPARE_MODE:
6158 if (!ValidateTextureCompareModeValue(context, params))
6159 {
6160 return false;
6161 }
6162 break;
6163
6164 case GL_TEXTURE_COMPARE_FUNC:
6165 if (!ValidateTextureCompareFuncValue(context, params))
6166 {
6167 return false;
6168 }
6169 break;
6170
6171 case GL_TEXTURE_SRGB_DECODE_EXT:
6172 if (!ValidateTextureSRGBDecodeValue(context, params))
6173 {
6174 return false;
6175 }
6176 break;
6177
Luc Ferron1b1a8642018-01-23 15:12:01 -05006178 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6179 {
6180 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6181 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6182 {
6183 return false;
6184 }
6185 }
6186 break;
6187
Jamie Madill9696d072017-08-26 23:19:57 -04006188 default:
6189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6190 return false;
6191 }
6192
6193 return true;
6194}
6195
6196template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6197template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6198
6199bool ValidateGetSamplerParameterBase(Context *context,
6200 GLuint sampler,
6201 GLenum pname,
6202 GLsizei *length)
6203{
6204 if (length)
6205 {
6206 *length = 0;
6207 }
6208
6209 if (context->getClientMajorVersion() < 3)
6210 {
6211 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6212 return false;
6213 }
6214
6215 if (!context->isSampler(sampler))
6216 {
6217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6218 return false;
6219 }
6220
6221 switch (pname)
6222 {
6223 case GL_TEXTURE_WRAP_S:
6224 case GL_TEXTURE_WRAP_T:
6225 case GL_TEXTURE_WRAP_R:
6226 case GL_TEXTURE_MIN_FILTER:
6227 case GL_TEXTURE_MAG_FILTER:
6228 case GL_TEXTURE_MIN_LOD:
6229 case GL_TEXTURE_MAX_LOD:
6230 case GL_TEXTURE_COMPARE_MODE:
6231 case GL_TEXTURE_COMPARE_FUNC:
6232 break;
6233
Luc Ferron1b1a8642018-01-23 15:12:01 -05006234 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6235 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6236 {
6237 return false;
6238 }
6239 break;
6240
Jamie Madill9696d072017-08-26 23:19:57 -04006241 case GL_TEXTURE_SRGB_DECODE_EXT:
6242 if (!context->getExtensions().textureSRGBDecode)
6243 {
6244 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6245 return false;
6246 }
6247 break;
6248
6249 default:
6250 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6251 return false;
6252 }
6253
6254 if (length)
6255 {
6256 *length = 1;
6257 }
6258 return true;
6259}
6260
6261bool ValidateGetInternalFormativBase(Context *context,
6262 GLenum target,
6263 GLenum internalformat,
6264 GLenum pname,
6265 GLsizei bufSize,
6266 GLsizei *numParams)
6267{
6268 if (numParams)
6269 {
6270 *numParams = 0;
6271 }
6272
6273 if (context->getClientMajorVersion() < 3)
6274 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006275 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006276 return false;
6277 }
6278
6279 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6280 if (!formatCaps.renderable)
6281 {
6282 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6283 return false;
6284 }
6285
6286 switch (target)
6287 {
6288 case GL_RENDERBUFFER:
6289 break;
6290
6291 case GL_TEXTURE_2D_MULTISAMPLE:
6292 if (context->getClientVersion() < ES_3_1)
6293 {
6294 context->handleError(InvalidOperation()
6295 << "Texture target requires at least OpenGL ES 3.1.");
6296 return false;
6297 }
6298 break;
6299
6300 default:
6301 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6302 return false;
6303 }
6304
6305 if (bufSize < 0)
6306 {
6307 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6308 return false;
6309 }
6310
6311 GLsizei maxWriteParams = 0;
6312 switch (pname)
6313 {
6314 case GL_NUM_SAMPLE_COUNTS:
6315 maxWriteParams = 1;
6316 break;
6317
6318 case GL_SAMPLES:
6319 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6320 break;
6321
6322 default:
6323 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6324 return false;
6325 }
6326
6327 if (numParams)
6328 {
6329 // glGetInternalFormativ will not overflow bufSize
6330 *numParams = std::min(bufSize, maxWriteParams);
6331 }
6332
6333 return true;
6334}
6335
Jamie Madille98b1b52018-03-08 09:47:23 -05006336// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
6337// implementation format info for incomplete framebuffers. It seems like these queries are
6338// incongruent with the other errors.
6339bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
6340{
6341 bool complete = false;
6342 ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
6343 if (!complete)
6344 {
6345 if (isFramebufferOp)
6346 {
6347 context->handleError(InvalidFramebufferOperation());
6348 }
6349 else
6350 {
6351 context->handleError(InvalidOperation());
6352 }
6353 return false;
6354 }
6355 return true;
6356}
6357
6358bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6359{
6360 GLint samples = 0;
6361 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
6362 if (samples != 0)
6363 {
6364 context->handleError(InvalidOperation());
6365 return false;
6366 }
6367 return true;
6368}
6369
Lingfeng Yang038dd532018-03-29 17:31:52 -07006370bool ValidateMultitextureUnit(Context *context, GLenum texture)
6371{
6372 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6373 {
6374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6375 return false;
6376 }
6377 return true;
6378}
6379
Jamie Madillc29968b2016-01-20 11:17:23 -05006380} // namespace gl