blob: 9d4ea712b61420a47f36522a0ccffb92c2e8a4f9 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040025#include "libANGLE/validationES2.h"
26#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28#include "common/mathutil.h"
29#include "common/utilities.h"
30
Jamie Madille2e406c2016-06-02 13:04:10 -040031using namespace angle;
32
Geoff Lange8ebe7f2013-08-05 15:03:13 -040033namespace gl
34{
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050037bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
38{
39 // List of compressed format that require that the texture size is smaller than or a multiple of
40 // the compressed block size.
41 switch (internalFormat)
42 {
43 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
44 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
46 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
47 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
51 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
52 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
53 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
57 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 return true;
jchen10a99ed552017-09-22 08:10:32 +080059
Luc Ferron9dbaeba2018-02-01 07:26:59 -050060 default:
61 return false;
62 }
63}
64bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
65{
66 // Compressed sub textures have additional formats that requires exact size.
67 // ES 3.1, Section 8.7, Page 171
68 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
69 IsETC2EACFormat(internalFormat);
70}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030071
72bool DifferenceCanOverflow(GLint a, GLint b)
73{
74 CheckedNumeric<GLint> checkedA(a);
75 checkedA -= b;
76 // Use negation to make sure that the difference can't overflow regardless of the order.
77 checkedA = -checkedA;
78 return !checkedA.IsValid();
79}
80
Jamie Madill5b772312018-03-08 20:28:32 -050081bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040082{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070083 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040084 const gl::Program *program = state.getProgram();
85
Corentin Wallez327411e2016-12-09 11:09:17 -050086 bool webglCompatibility = context->getExtensions().webglCompatibility;
87
Jamie Madill51af38b2018-04-15 08:50:56 -040088 const VertexArray *vao = state.getVertexArray();
89 const AttributesMask &clientAttribs = vao->getEnabledClientMemoryAttribsMask();
90
91 if (clientAttribs.any())
92 {
93 if (webglCompatibility || !state.areClientArraysEnabled())
94 {
95 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
96 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
97 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
98 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
99 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
100 return false;
101 }
102 else if (vao->hasEnabledNullPointerClientArray())
103 {
104 // This is an application error that would normally result in a crash, but we catch it
105 // and return an error
106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
107 return false;
108 }
109 }
110
111 // If we're drawing zero vertices, we have enough data.
112 if (vertexCount <= 0 || primcount <= 0)
113 {
114 return true;
115 }
116
Jamie Madill231c7f52017-04-26 13:45:37 -0400117 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800118 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill51af38b2018-04-15 08:50:56 -0400119
Jamie Madill02c9c042018-04-17 13:43:48 -0400120 const AttributesMask &activeAttribs = (program->getActiveAttribLocationsMask() &
121 vao->getEnabledAttributesMask() & ~clientAttribs);
Jamie Madill51af38b2018-04-15 08:50:56 -0400122
123 for (size_t attributeIndex : activeAttribs)
Jamie Madill1ca74672015-07-21 15:14:11 -0400124 {
125 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400126 ASSERT(attrib.enabled);
Corentin Wallez672f7f32017-06-15 17:42:17 -0400127
Lingfeng Yang038dd532018-03-29 17:31:52 -0700128 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400129 ASSERT(program->isAttribLocationActive(attributeIndex));
Corentin Wallezfd456442016-12-21 17:57:00 -0500130
Jamie Madill02c9c042018-04-17 13:43:48 -0400131 GLint maxVertexElement = maxVertex;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300132 GLuint divisor = binding.getDivisor();
Jamie Madill02c9c042018-04-17 13:43:48 -0400133 if (divisor != 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300135 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 }
137
138 // We do manual overflow checks here instead of using safe_math.h because it was
139 // a bottleneck. Thanks to some properties of GL we know inequalities that can
140 // help us make the overflow checks faster.
141
142 // The max possible attribSize is 16 for a vector of 4 32 bit values.
143 constexpr uint64_t kMaxAttribSize = 16;
144 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
145 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
146
147 // We know attribStride is given as a GLsizei which is typedefed to int.
148 // We also know an upper bound for attribSize.
Jamie Madill02c9c042018-04-17 13:43:48 -0400149 static_assert(std::is_same<int, GLsizei>::value, "Unexpected type");
150 ASSERT(ComputeVertexAttributeStride(attrib, binding) == binding.getStride());
151 uint64_t attribStride = binding.getStride();
152 ASSERT(attribStride <= kIntMax && ComputeVertexAttributeTypeSize(attrib) <= kMaxAttribSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500153
Jamie Madill02c9c042018-04-17 13:43:48 -0400154 // Computing the product of two 32-bit ints will fit in 64 bits without overflow.
155 static_assert(kIntMax * kIntMax < kUint64Max, "Unexpected overflow");
156 uint64_t attribDataSizeMinusAttribSize = maxVertexElement * attribStride;
Corentin Wallezfd456442016-12-21 17:57:00 -0500157
158 // An overflow can happen when adding the offset, check for it.
Jamie Madill02c9c042018-04-17 13:43:48 -0400159 if (attribDataSizeMinusAttribSize > kUint64Max - attrib.cachedSizePlusRelativeOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500160 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500162 return false;
163 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500164
165 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
Jamie Madill02c9c042018-04-17 13:43:48 -0400166 // We can return INVALID_OPERATION if our array buffer does not have enough backing data.
167 if (attribDataSizeMinusAttribSize + attrib.cachedSizePlusRelativeOffset >
168 binding.getCachedBufferSizeMinusOffset())
Corentin Wallezfd456442016-12-21 17:57:00 -0500169 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500171 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400172 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400173 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800174
Jamie Madill7267aa62018-04-17 15:28:21 -0400175 if (webglCompatibility && vao->hasTransformFeedbackBindingConflict(activeAttribs))
Jamie Madill02c9c042018-04-17 13:43:48 -0400176 {
Jamie Madill7267aa62018-04-17 15:28:21 -0400177 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexBufferBoundForTransformFeedback);
178 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400179 }
180
181 return true;
182}
183
Jamie Madill5b772312018-03-08 20:28:32 -0500184bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400185{
186 switch (type)
187 {
188 // Types referenced in Table 3.4 of the ES 2.0.25 spec
189 case GL_UNSIGNED_BYTE:
190 case GL_UNSIGNED_SHORT_4_4_4_4:
191 case GL_UNSIGNED_SHORT_5_5_5_1:
192 case GL_UNSIGNED_SHORT_5_6_5:
193 return context->getClientVersion() >= ES_2_0;
194
195 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
196 case GL_BYTE:
197 case GL_INT:
198 case GL_SHORT:
199 case GL_UNSIGNED_INT:
200 case GL_UNSIGNED_INT_10F_11F_11F_REV:
201 case GL_UNSIGNED_INT_24_8:
202 case GL_UNSIGNED_INT_2_10_10_10_REV:
203 case GL_UNSIGNED_INT_5_9_9_9_REV:
204 case GL_UNSIGNED_SHORT:
205 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
206 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
207 return context->getClientVersion() >= ES_3_0;
208
209 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400210 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
211 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400212
213 case GL_HALF_FLOAT:
214 return context->getClientVersion() >= ES_3_0 ||
215 context->getExtensions().textureHalfFloat;
216
217 case GL_HALF_FLOAT_OES:
218 return context->getExtensions().colorBufferHalfFloat;
219
220 default:
221 return false;
222 }
223}
224
Jamie Madill5b772312018-03-08 20:28:32 -0500225bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400226{
227 switch (format)
228 {
229 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
230 case GL_RGBA:
231 case GL_RGB:
232 case GL_ALPHA:
233 return context->getClientVersion() >= ES_2_0;
234
235 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
236 case GL_RG:
237 case GL_RED:
238 case GL_RGBA_INTEGER:
239 case GL_RGB_INTEGER:
240 case GL_RG_INTEGER:
241 case GL_RED_INTEGER:
242 return context->getClientVersion() >= ES_3_0;
243
244 case GL_SRGB_ALPHA_EXT:
245 case GL_SRGB_EXT:
246 return context->getExtensions().sRGB;
247
248 case GL_BGRA_EXT:
249 return context->getExtensions().readFormatBGRA;
250
251 default:
252 return false;
253 }
254}
255
Jamie Madill5b772312018-03-08 20:28:32 -0500256bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400257 GLenum framebufferComponentType,
258 GLenum format,
259 GLenum type)
260{
261 switch (framebufferComponentType)
262 {
263 case GL_UNSIGNED_NORMALIZED:
264 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
265 // ReadPixels with BGRA even if the extension is not present
266 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
267 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
268 type == GL_UNSIGNED_BYTE);
269
270 case GL_SIGNED_NORMALIZED:
271 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
272
273 case GL_INT:
274 return (format == GL_RGBA_INTEGER && type == GL_INT);
275
276 case GL_UNSIGNED_INT:
277 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
278
279 case GL_FLOAT:
280 return (format == GL_RGBA && type == GL_FLOAT);
281
282 default:
283 UNREACHABLE();
284 return false;
285 }
286}
287
Geoff Langc1984ed2016-10-07 12:41:00 -0400288template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400289bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400290{
291 switch (ConvertToGLenum(params[0]))
292 {
293 case GL_CLAMP_TO_EDGE:
294 break;
295
296 case GL_REPEAT:
297 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400298 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400299 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400300 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700301 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400302 return false;
303 }
304 break;
305
306 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400308 return false;
309 }
310
311 return true;
312}
313
314template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400315bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400316{
317 switch (ConvertToGLenum(params[0]))
318 {
319 case GL_NEAREST:
320 case GL_LINEAR:
321 break;
322
323 case GL_NEAREST_MIPMAP_NEAREST:
324 case GL_LINEAR_MIPMAP_NEAREST:
325 case GL_NEAREST_MIPMAP_LINEAR:
326 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400327 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400328 {
329 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700330 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400331 return false;
332 }
333 break;
334
335 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700336 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400337 return false;
338 }
339
340 return true;
341}
342
343template <typename ParamType>
344bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
345{
346 switch (ConvertToGLenum(params[0]))
347 {
348 case GL_NEAREST:
349 case GL_LINEAR:
350 break;
351
352 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700353 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400354 return false;
355 }
356
357 return true;
358}
359
360template <typename ParamType>
361bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
362{
363 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
364 switch (ConvertToGLenum(params[0]))
365 {
366 case GL_NONE:
367 case GL_COMPARE_REF_TO_TEXTURE:
368 break;
369
370 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400372 return false;
373 }
374
375 return true;
376}
377
378template <typename ParamType>
379bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
380{
381 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
382 switch (ConvertToGLenum(params[0]))
383 {
384 case GL_LEQUAL:
385 case GL_GEQUAL:
386 case GL_LESS:
387 case GL_GREATER:
388 case GL_EQUAL:
389 case GL_NOTEQUAL:
390 case GL_ALWAYS:
391 case GL_NEVER:
392 break;
393
394 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700395 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400396 return false;
397 }
398
399 return true;
400}
401
402template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700403bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
404{
405 if (!context->getExtensions().textureSRGBDecode)
406 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700408 return false;
409 }
410
411 switch (ConvertToGLenum(params[0]))
412 {
413 case GL_DECODE_EXT:
414 case GL_SKIP_DECODE_EXT:
415 break;
416
417 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700418 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700419 return false;
420 }
421
422 return true;
423}
424
Luc Ferron1b1a8642018-01-23 15:12:01 -0500425bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
426{
427 if (!context->getExtensions().textureFilterAnisotropic)
428 {
429 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
430 return false;
431 }
432
433 return true;
434}
435
436bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
437{
438 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
439 {
440 return false;
441 }
442
443 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
444
445 if (paramValue < 1 || paramValue > largest)
446 {
447 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
448 return false;
449 }
450
451 return true;
452}
453
Jamie Madill5b772312018-03-08 20:28:32 -0500454bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400455{
456 const Program *program = context->getGLState().getProgram();
457 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
458
Brandon Jonesc405ae72017-12-06 14:15:03 -0800459 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
460 framebuffer->getDrawBufferTypeMask().to_ulong(),
461 program->getActiveOutputVariables().to_ulong(),
462 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400463 {
Brandon Jones76746f92017-11-22 11:44:41 -0800464 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
465 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400466 }
467
468 return true;
469}
470
Jamie Madill5b772312018-03-08 20:28:32 -0500471bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400472{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700473 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400474 const Program *program = context->getGLState().getProgram();
475 const VertexArray *vao = context->getGLState().getVertexArray();
476
Brandon Jonesc405ae72017-12-06 14:15:03 -0800477 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
478 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
479 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
480
481 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
482 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
483 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
484
485 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
486 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400487 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800488 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
489 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400490 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400491 return true;
492}
493
Jiawei Shaofccebff2018-03-08 13:51:02 +0800494bool IsCompatibleDrawModeWithGeometryShader(GLenum drawMode,
495 GLenum geometryShaderInputPrimitiveType)
496{
497 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
498 switch (geometryShaderInputPrimitiveType)
499 {
500 case GL_POINTS:
501 return drawMode == GL_POINTS;
502 case GL_LINES:
503 return drawMode == GL_LINES || drawMode == GL_LINE_STRIP || drawMode == GL_LINE_LOOP;
504 case GL_LINES_ADJACENCY_EXT:
505 return drawMode == GL_LINES_ADJACENCY_EXT || drawMode == GL_LINE_STRIP_ADJACENCY_EXT;
506 case GL_TRIANGLES:
507 return drawMode == GL_TRIANGLES || drawMode == GL_TRIANGLE_FAN ||
508 drawMode == GL_TRIANGLE_STRIP;
509 case GL_TRIANGLES_ADJACENCY_EXT:
510 return drawMode == GL_TRIANGLES_ADJACENCY_EXT ||
511 drawMode == GL_TRIANGLE_STRIP_ADJACENCY_EXT;
512 default:
513 UNREACHABLE();
514 return false;
515 }
516}
517
Geoff Langf41a7152016-09-19 15:11:17 -0400518} // anonymous namespace
519
Brandon Jonesd1049182018-03-28 10:02:20 -0700520void SetRobustLengthParam(GLsizei *length, GLsizei value)
521{
522 if (length)
523 {
524 *length = value;
525 }
526}
527
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500528bool IsETC2EACFormat(const GLenum format)
529{
530 // ES 3.1, Table 8.19
531 switch (format)
532 {
533 case GL_COMPRESSED_R11_EAC:
534 case GL_COMPRESSED_SIGNED_R11_EAC:
535 case GL_COMPRESSED_RG11_EAC:
536 case GL_COMPRESSED_SIGNED_RG11_EAC:
537 case GL_COMPRESSED_RGB8_ETC2:
538 case GL_COMPRESSED_SRGB8_ETC2:
539 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
540 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
541 case GL_COMPRESSED_RGBA8_ETC2_EAC:
542 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
543 return true;
544
545 default:
546 return false;
547 }
548}
549
Jamie Madill5b772312018-03-08 20:28:32 -0500550bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400551{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800552 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400553 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800554 case TextureType::_2D:
555 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800556 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400557
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800558 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400559 return context->getExtensions().textureRectangle;
560
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800561 case TextureType::_3D:
562 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800563 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500564
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800565 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800566 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400567
He Yunchaoced53ae2016-11-29 15:00:51 +0800568 default:
569 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500570 }
Jamie Madill35d15012013-10-07 10:46:37 -0400571}
572
Jamie Madill5b772312018-03-08 20:28:32 -0500573bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500574{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800575 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500576 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800577 case TextureType::_2D:
578 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500579 return true;
580
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800581 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400582 return context->getExtensions().textureRectangle;
583
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500584 default:
585 return false;
586 }
587}
588
Jamie Madill5b772312018-03-08 20:28:32 -0500589bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500590{
591 switch (target)
592 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800593 case TextureType::_3D:
594 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300595 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500596
597 default:
598 return false;
599 }
600}
601
Ian Ewellbda75592016-04-18 17:25:54 -0400602// Most texture GL calls are not compatible with external textures, so we have a separate validation
603// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500604bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400605{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800606 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400607 (context->getExtensions().eglImageExternal ||
608 context->getExtensions().eglStreamConsumerExternal);
609}
610
Shannon Woods4dfed832014-03-17 20:03:39 -0400611// This function differs from ValidTextureTarget in that the target must be
612// usable as the destination of a 2D operation-- so a cube face is valid, but
613// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400614// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500615bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400616{
617 switch (target)
618 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800619 case TextureTarget::_2D:
620 case TextureTarget::CubeMapNegativeX:
621 case TextureTarget::CubeMapNegativeY:
622 case TextureTarget::CubeMapNegativeZ:
623 case TextureTarget::CubeMapPositiveX:
624 case TextureTarget::CubeMapPositiveY:
625 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800626 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800627 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400628 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800629 default:
630 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500631 }
632}
633
Jamie Madill5b772312018-03-08 20:28:32 -0500634bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -0400635 GLenum mode,
636 GLsizei count,
637 GLenum type,
638 const GLvoid *indices,
639 GLsizei primcount)
640{
641 if (primcount < 0)
642 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700643 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400644 return false;
645 }
646
647 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
648 {
649 return false;
650 }
651
Jamie Madill9fdaa492018-02-16 10:52:11 -0500652 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400653}
654
655bool ValidateDrawArraysInstancedBase(Context *context,
656 GLenum mode,
657 GLint first,
658 GLsizei count,
659 GLsizei primcount)
660{
661 if (primcount < 0)
662 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700663 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400664 return false;
665 }
666
667 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
668 {
669 return false;
670 }
671
Jamie Madill9fdaa492018-02-16 10:52:11 -0500672 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400673}
674
Jamie Madill5b772312018-03-08 20:28:32 -0500675bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400676{
677 // Verify there is at least one active attribute with a divisor of zero
678 const State &state = context->getGLState();
679
680 Program *program = state.getProgram();
681
682 const auto &attribs = state.getVertexArray()->getVertexAttributes();
683 const auto &bindings = state.getVertexArray()->getVertexBindings();
684 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
685 {
686 const VertexAttribute &attrib = attribs[attributeIndex];
687 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300688 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400689 {
690 return true;
691 }
692 }
693
Brandon Jonesafa75152017-07-21 13:11:29 -0700694 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400695 return false;
696}
697
Jamie Madill5b772312018-03-08 20:28:32 -0500698bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500699{
700 switch (target)
701 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800702 case TextureType::_3D:
703 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800704 return true;
705 default:
706 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400707 }
708}
709
Jamie Madill5b772312018-03-08 20:28:32 -0500710bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800711{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800712 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800713 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800714 case TextureType::_2D:
715 case TextureType::_2DArray:
716 case TextureType::_2DMultisample:
717 case TextureType::CubeMap:
718 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800719 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800720 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400721 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800722 default:
723 return false;
724 }
725}
726
Jamie Madill5b772312018-03-08 20:28:32 -0500727bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500728{
He Yunchaoced53ae2016-11-29 15:00:51 +0800729 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
730 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400731 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500732
733 switch (target)
734 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800735 case GL_FRAMEBUFFER:
736 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400737
He Yunchaoced53ae2016-11-29 15:00:51 +0800738 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800739 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400740 return (context->getExtensions().framebufferBlit ||
741 context->getClientMajorVersion() >= 3);
742
He Yunchaoced53ae2016-11-29 15:00:51 +0800743 default:
744 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500745 }
746}
747
Jamie Madill5b772312018-03-08 20:28:32 -0500748bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400749{
Jamie Madillc29968b2016-01-20 11:17:23 -0500750 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400751 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800752 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400753 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800754 case TextureType::_2D:
755 case TextureType::_2DArray:
756 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500757 maxDimension = caps.max2DTextureSize;
758 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800759 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800760 maxDimension = caps.maxCubeMapTextureSize;
761 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800762 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400763 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800764 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800765 maxDimension = caps.max3DTextureSize;
766 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800767 default:
768 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400769 }
770
Brandon Jones6cad5662017-06-14 13:25:13 -0700771 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400772}
773
Jamie Madill5b772312018-03-08 20:28:32 -0500774bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800775 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700776 GLint level,
777 GLsizei width,
778 GLsizei height,
779 GLsizei depth,
780 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400781{
Brandon Jones6cad5662017-06-14 13:25:13 -0700782 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400783 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700784 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400785 return false;
786 }
Austin Kinross08528e12015-10-07 16:24:40 -0700787 // TexSubImage parameters can be NPOT without textureNPOT extension,
788 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500789 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500790 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500791 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400792 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400793 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700794 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400795 return false;
796 }
797
798 if (!ValidMipLevel(context, target, level))
799 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700800 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400801 return false;
802 }
803
804 return true;
805}
806
Geoff Lang966c9402017-04-18 12:38:27 -0400807bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
808{
809 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
810 (size % blockSize == 0);
811}
812
Jamie Madill5b772312018-03-08 20:28:32 -0500813bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500814 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400815 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500816 GLsizei width,
817 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400818{
Geoff Langca271392017-04-05 12:30:00 -0400819 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400820 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400821 {
822 return false;
823 }
824
Geoff Lang966c9402017-04-18 12:38:27 -0400825 if (width < 0 || height < 0)
826 {
827 return false;
828 }
829
830 if (CompressedTextureFormatRequiresExactSize(internalFormat))
831 {
832 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
833 // block size for level 0 but WebGL disallows this.
834 bool smallerThanBlockSizeAllowed =
835 level > 0 || !context->getExtensions().webglCompatibility;
836
837 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
838 smallerThanBlockSizeAllowed) ||
839 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
840 smallerThanBlockSizeAllowed))
841 {
842 return false;
843 }
844 }
845
846 return true;
847}
848
Jamie Madill5b772312018-03-08 20:28:32 -0500849bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400850 GLenum internalFormat,
851 GLint xoffset,
852 GLint yoffset,
853 GLsizei width,
854 GLsizei height,
855 size_t textureWidth,
856 size_t textureHeight)
857{
858 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
859 if (!formatInfo.compressed)
860 {
861 return false;
862 }
863
Geoff Lang44ff5a72017-02-03 15:15:43 -0500864 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400865 {
866 return false;
867 }
868
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500869 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400870 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500871 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400872 yoffset % formatInfo.compressedBlockHeight != 0)
873 {
874 return false;
875 }
876
877 // Allowed to either have data that is a multiple of block size or is smaller than the block
878 // size but fills the entire mip
879 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
880 static_cast<size_t>(width) == textureWidth &&
881 static_cast<size_t>(height) == textureHeight;
882 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
883 (height % formatInfo.compressedBlockHeight) == 0;
884 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400885 {
886 return false;
887 }
888 }
889
Geoff Langd4f180b2013-09-24 13:57:44 -0400890 return true;
891}
892
Jamie Madill5b772312018-03-08 20:28:32 -0500893bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800894 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400895 GLsizei width,
896 GLsizei height,
897 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400898 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400899 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400900 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400901 GLsizei imageSize)
902{
Corentin Wallez336129f2017-10-17 15:55:40 -0400903 gl::Buffer *pixelUnpackBuffer =
904 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400905 if (pixelUnpackBuffer == nullptr && imageSize < 0)
906 {
907 // Checks are not required
908 return true;
909 }
910
911 // ...the data would be unpacked from the buffer object such that the memory reads required
912 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400913 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
914 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400915 const gl::Extents size(width, height, depth);
916 const auto &unpack = context->getGLState().getUnpackState();
917
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800918 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400919 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
920 if (endByteOrErr.isError())
921 {
922 context->handleError(endByteOrErr.getError());
923 return false;
924 }
925
926 GLuint endByte = endByteOrErr.getResult();
927
928 if (pixelUnpackBuffer)
929 {
930 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
931 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
932 checkedEndByte += checkedOffset;
933
934 if (!checkedEndByte.IsValid() ||
935 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
936 {
937 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500938 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400939 return false;
940 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800941 if (context->getExtensions().webglCompatibility &&
942 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
943 {
944 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
945 PixelUnpackBufferBoundForTransformFeedback);
946 return false;
947 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400948 }
949 else
950 {
951 ASSERT(imageSize >= 0);
952 if (pixels == nullptr && imageSize != 0)
953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500954 context->handleError(InvalidOperation()
955 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400956 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400957 }
958
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400959 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500961 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400962 return false;
963 }
964 }
965
966 return true;
967}
968
Geoff Lang37dde692014-01-31 16:34:54 -0500969bool ValidQueryType(const Context *context, GLenum queryType)
970{
He Yunchaoced53ae2016-11-29 15:00:51 +0800971 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
972 "GL extension enums not equal.");
973 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
974 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500975
976 switch (queryType)
977 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800978 case GL_ANY_SAMPLES_PASSED:
979 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400980 return context->getClientMajorVersion() >= 3 ||
981 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
983 return (context->getClientMajorVersion() >= 3);
984 case GL_TIME_ELAPSED_EXT:
985 return context->getExtensions().disjointTimerQuery;
986 case GL_COMMANDS_COMPLETED_CHROMIUM:
987 return context->getExtensions().syncQuery;
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800988 case GL_PRIMITIVES_GENERATED_EXT:
989 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800990 default:
991 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500992 }
993}
994
Jamie Madill5b772312018-03-08 20:28:32 -0500995bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400996 GLenum type,
997 GLboolean normalized,
998 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400999 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001000 bool pureInteger)
1001{
1002 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001003 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1004 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1005 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1006 // parameter exceeds 255.
1007 constexpr GLsizei kMaxWebGLStride = 255;
1008 if (stride > kMaxWebGLStride)
1009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001010 context->handleError(InvalidValue()
1011 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001012 return false;
1013 }
1014
1015 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1016 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1017 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1018 // or an INVALID_OPERATION error is generated.
1019 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1020 size_t typeSize = GetVertexFormatTypeSize(internalType);
1021
1022 ASSERT(isPow2(typeSize) && typeSize > 0);
1023 size_t sizeMask = (typeSize - 1);
1024 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001026 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001027 return false;
1028 }
1029
1030 if ((stride & sizeMask) != 0)
1031 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001032 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001033 return false;
1034 }
1035
1036 return true;
1037}
1038
Jamie Madill5b772312018-03-08 20:28:32 -05001039Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001040{
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1042 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1043 // or program object and INVALID_OPERATION if the provided name identifies an object
1044 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001045
Dian Xiang769769a2015-09-09 15:20:08 -07001046 Program *validProgram = context->getProgram(id);
1047
1048 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001049 {
Dian Xiang769769a2015-09-09 15:20:08 -07001050 if (context->getShader(id))
1051 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001052 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001053 }
1054 else
1055 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001056 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001057 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001058 }
Dian Xiang769769a2015-09-09 15:20:08 -07001059
1060 return validProgram;
1061}
1062
Jamie Madill5b772312018-03-08 20:28:32 -05001063Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001064{
1065 // See ValidProgram for spec details.
1066
1067 Shader *validShader = context->getShader(id);
1068
1069 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001070 {
Dian Xiang769769a2015-09-09 15:20:08 -07001071 if (context->getProgram(id))
1072 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001074 }
1075 else
1076 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001077 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001078 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001079 }
Dian Xiang769769a2015-09-09 15:20:08 -07001080
1081 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001082}
1083
Geoff Langb1196682014-07-23 13:47:29 -04001084bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001085{
Geoff Langfa125c92017-10-24 13:01:46 -04001086 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001087 {
Geoff Langfa125c92017-10-24 13:01:46 -04001088 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1089 {
1090 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1091 return false;
1092 }
Jamie Madillb4472272014-07-03 10:38:55 -04001093
Geoff Langfa125c92017-10-24 13:01:46 -04001094 // Color attachment 0 is validated below because it is always valid
1095 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001096 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001097 {
Geoff Langfa125c92017-10-24 13:01:46 -04001098 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001099 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001100 }
1101 }
1102 else
1103 {
1104 switch (attachment)
1105 {
Geoff Langfa125c92017-10-24 13:01:46 -04001106 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001107 case GL_DEPTH_ATTACHMENT:
1108 case GL_STENCIL_ATTACHMENT:
1109 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001110
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 case GL_DEPTH_STENCIL_ATTACHMENT:
1112 if (!context->getExtensions().webglCompatibility &&
1113 context->getClientMajorVersion() < 3)
1114 {
Geoff Langfa125c92017-10-24 13:01:46 -04001115 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001116 return false;
1117 }
1118 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001119
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001122 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001123 }
1124 }
1125
1126 return true;
1127}
1128
Jamie Madill5b772312018-03-08 20:28:32 -05001129bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001130 GLenum target,
1131 GLsizei samples,
1132 GLenum internalformat,
1133 GLsizei width,
1134 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001135{
1136 switch (target)
1137 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001138 case GL_RENDERBUFFER:
1139 break;
1140 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001141 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001142 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001143 }
1144
1145 if (width < 0 || height < 0 || samples < 0)
1146 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001147 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001148 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001149 }
1150
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001151 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1152 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1153
1154 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001155 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001157 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001158 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001159 }
1160
1161 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1162 // 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 -08001163 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001164 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1165 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001166 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001168 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001169 }
1170
Geoff Langaae65a42014-05-26 12:43:44 -04001171 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001173 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001174 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001175 }
1176
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001177 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001178 if (handle == 0)
1179 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 }
1183
1184 return true;
1185}
1186
He Yunchaoced53ae2016-11-29 15:00:51 +08001187bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1188 GLenum target,
1189 GLenum attachment,
1190 GLenum renderbuffertarget,
1191 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001192{
Geoff Lange8afa902017-09-27 15:00:43 -04001193 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001195 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001196 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001197 }
1198
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001199 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001200
Jamie Madill84115c92015-04-23 15:00:07 -04001201 ASSERT(framebuffer);
1202 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001203 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001204 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001205 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001206 }
1207
Jamie Madillb4472272014-07-03 10:38:55 -04001208 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001209 {
Jamie Madillb4472272014-07-03 10:38:55 -04001210 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001211 }
1212
Jamie Madillab9d82c2014-01-21 16:38:14 -05001213 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1214 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1215 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1216 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1217 if (renderbuffer != 0)
1218 {
1219 if (!context->getRenderbuffer(renderbuffer))
1220 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001222 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001223 }
1224 }
1225
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001226 return true;
1227}
1228
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001229bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001230 GLint srcX0,
1231 GLint srcY0,
1232 GLint srcX1,
1233 GLint srcY1,
1234 GLint dstX0,
1235 GLint dstY0,
1236 GLint dstX1,
1237 GLint dstY1,
1238 GLbitfield mask,
1239 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001240{
1241 switch (filter)
1242 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001243 case GL_NEAREST:
1244 break;
1245 case GL_LINEAR:
1246 break;
1247 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001248 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001249 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001250 }
1251
1252 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001254 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001255 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 }
1257
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001258 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1259 // color buffer, leaving only nearest being unfiltered from above
1260 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001262 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001263 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001264 }
1265
Jamie Madill51f40ec2016-06-15 14:06:00 -04001266 const auto &glState = context->getGLState();
1267 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1268 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001269
1270 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001272 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001273 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 }
1275
Jamie Madill427064d2018-04-13 16:20:34 -04001276 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001277 {
Jamie Madill48faf802014-11-06 15:27:22 -05001278 return false;
1279 }
1280
Jamie Madill427064d2018-04-13 16:20:34 -04001281 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001282 {
Jamie Madill48faf802014-11-06 15:27:22 -05001283 return false;
1284 }
1285
Qin Jiajiaaef92162018-02-27 13:51:44 +08001286 if (readFramebuffer->id() == drawFramebuffer->id())
1287 {
1288 context->handleError(InvalidOperation());
1289 return false;
1290 }
1291
Jamie Madille98b1b52018-03-08 09:47:23 -05001292 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 {
Geoff Langb1196682014-07-23 13:47:29 -04001294 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295 }
1296
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001297 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1298 // always run it in order to avoid triggering driver bugs.
1299 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1300 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001301 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001302 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1303 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001304 }
1305
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1307
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001308 if (mask & GL_COLOR_BUFFER_BIT)
1309 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001310 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001311 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312
He Yunchao66a41a22016-12-15 16:45:05 +08001313 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001315 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001316
Geoff Langa15472a2015-08-11 11:48:03 -04001317 for (size_t drawbufferIdx = 0;
1318 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001319 {
Geoff Langa15472a2015-08-11 11:48:03 -04001320 const FramebufferAttachment *attachment =
1321 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1322 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001324 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325
Geoff Langb2f3d052013-08-13 12:49:27 -04001326 // The GL ES 3.0.2 spec (pg 193) states that:
1327 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001328 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1329 // as well
1330 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1331 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001332 // Changes with EXT_color_buffer_float:
1333 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001334 GLenum readComponentType = readFormat.info->componentType;
1335 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001336 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001337 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001338 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001339 drawComponentType == GL_SIGNED_NORMALIZED);
1340
1341 if (extensions.colorBufferFloat)
1342 {
1343 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1344 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1345
1346 if (readFixedOrFloat != drawFixedOrFloat)
1347 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001348 context->handleError(InvalidOperation()
1349 << "If the read buffer contains fixed-point or "
1350 "floating-point values, the draw buffer must "
1351 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001352 return false;
1353 }
1354 }
1355 else if (readFixedPoint != drawFixedPoint)
1356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 context->handleError(InvalidOperation()
1358 << "If the read buffer contains fixed-point values, "
1359 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001360 return false;
1361 }
1362
1363 if (readComponentType == GL_UNSIGNED_INT &&
1364 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001366 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001367 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368 }
1369
Jamie Madill6163c752015-12-07 16:32:59 -05001370 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001372 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001373 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001374 }
1375
Jamie Madilla3944d42016-07-22 22:13:26 -04001376 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001377 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001379 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001380 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 }
Geoff Lange4915782017-04-12 15:19:07 -04001382
1383 if (context->getExtensions().webglCompatibility &&
1384 *readColorBuffer == *attachment)
1385 {
1386 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 InvalidOperation()
1388 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001389 return false;
1390 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001391 }
1392 }
1393
Jamie Madilla3944d42016-07-22 22:13:26 -04001394 if ((readFormat.info->componentType == GL_INT ||
1395 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1396 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001398 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001399 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 }
He Yunchao66a41a22016-12-15 16:45:05 +08001402 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1403 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1404 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1405 // situation is an application error that would lead to a crash in ANGLE.
1406 else if (drawFramebuffer->hasEnabledDrawBuffer())
1407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001408 context->handleError(
1409 InvalidOperation()
1410 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001411 return false;
1412 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 }
1414
He Yunchaoced53ae2016-11-29 15:00:51 +08001415 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001416 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1417 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001419 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001420 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001421 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001422 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001423 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001424 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001426 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 {
Kenneth Russell69382852017-07-21 16:38:44 -04001428 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001430 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001431 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001434 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001436 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001437 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001438 }
Geoff Lange4915782017-04-12 15:19:07 -04001439
1440 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001442 context->handleError(
1443 InvalidOperation()
1444 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001445 return false;
1446 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001447 }
He Yunchao66a41a22016-12-15 16:45:05 +08001448 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1449 else if (drawBuffer)
1450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001451 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1452 "depth/stencil attachment of a "
1453 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001454 return false;
1455 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001456 }
1457 }
1458
Martin Radeva3ed4572017-07-27 18:29:37 +03001459 // ANGLE_multiview, Revision 1:
1460 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1461 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1462 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1463 {
1464 context->handleError(InvalidFramebufferOperation()
1465 << "Attempt to read from a multi-view framebuffer.");
1466 return false;
1467 }
1468 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1469 {
1470 context->handleError(InvalidFramebufferOperation()
1471 << "Attempt to write to a multi-view framebuffer.");
1472 return false;
1473 }
1474
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001475 return true;
1476}
1477
Jamie Madill4928b7c2017-06-20 12:57:39 -04001478bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001479 GLint x,
1480 GLint y,
1481 GLsizei width,
1482 GLsizei height,
1483 GLenum format,
1484 GLenum type,
1485 GLsizei bufSize,
1486 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001487 GLsizei *columns,
1488 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001489 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001490{
1491 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001492 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 return false;
1494 }
1495
Brandon Jonesd1049182018-03-28 10:02:20 -07001496 GLsizei writeLength = 0;
1497 GLsizei writeColumns = 0;
1498 GLsizei writeRows = 0;
1499
1500 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1501 &writeColumns, &writeRows, pixels))
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 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001507 {
Geoff Langb1196682014-07-23 13:47:29 -04001508 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001509 }
1510
Brandon Jonesd1049182018-03-28 10:02:20 -07001511 SetRobustLengthParam(length, writeLength);
1512 SetRobustLengthParam(columns, writeColumns);
1513 SetRobustLengthParam(rows, writeRows);
1514
Jamie Madillc29968b2016-01-20 11:17:23 -05001515 return true;
1516}
1517
1518bool ValidateReadnPixelsEXT(Context *context,
1519 GLint x,
1520 GLint y,
1521 GLsizei width,
1522 GLsizei height,
1523 GLenum format,
1524 GLenum type,
1525 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001526 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001527{
1528 if (bufSize < 0)
1529 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001530 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001531 return false;
1532 }
1533
Geoff Lang62fce5b2016-09-30 10:46:35 -04001534 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001535 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001536}
Jamie Madill26e91952014-03-05 15:01:27 -05001537
Jamie Madill4928b7c2017-06-20 12:57:39 -04001538bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001539 GLint x,
1540 GLint y,
1541 GLsizei width,
1542 GLsizei height,
1543 GLenum format,
1544 GLenum type,
1545 GLsizei bufSize,
1546 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001547 GLsizei *columns,
1548 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001549 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001550{
Brandon Jonesd1049182018-03-28 10:02:20 -07001551 GLsizei writeLength = 0;
1552 GLsizei writeColumns = 0;
1553 GLsizei writeRows = 0;
1554
Geoff Lang62fce5b2016-09-30 10:46:35 -04001555 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001556 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001557 return false;
1558 }
1559
Brandon Jonesd1049182018-03-28 10:02:20 -07001560 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1561 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001562 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001563 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001564 }
1565
Brandon Jonesd1049182018-03-28 10:02:20 -07001566 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001567 {
1568 return false;
1569 }
1570
Brandon Jonesd1049182018-03-28 10:02:20 -07001571 SetRobustLengthParam(length, writeLength);
1572 SetRobustLengthParam(columns, writeColumns);
1573 SetRobustLengthParam(rows, writeRows);
1574
Geoff Lang62fce5b2016-09-30 10:46:35 -04001575 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001576}
1577
Jamie Madillf0e04492017-08-26 15:28:42 -04001578bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001579{
1580 if (!context->getExtensions().occlusionQueryBoolean &&
1581 !context->getExtensions().disjointTimerQuery)
1582 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001583 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001584 return false;
1585 }
1586
Olli Etuaho41997e72016-03-10 13:38:39 +02001587 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001588}
1589
Jamie Madillf0e04492017-08-26 15:28:42 -04001590bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001591{
1592 if (!context->getExtensions().occlusionQueryBoolean &&
1593 !context->getExtensions().disjointTimerQuery)
1594 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001595 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001596 return false;
1597 }
1598
Olli Etuaho41997e72016-03-10 13:38:39 +02001599 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001600}
1601
Jamie Madillf0e04492017-08-26 15:28:42 -04001602bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1603{
1604 if (!context->getExtensions().occlusionQueryBoolean &&
1605 !context->getExtensions().disjointTimerQuery)
1606 {
1607 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1608 return false;
1609 }
1610
1611 return true;
1612}
1613
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001614bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001615{
1616 if (!ValidQueryType(context, target))
1617 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001618 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001619 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001620 }
1621
1622 if (id == 0)
1623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001624 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001625 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001626 }
1627
1628 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1629 // of zero, if the active query object name for <target> is non-zero (for the
1630 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1631 // the active query for either target is non-zero), if <id> is the name of an
1632 // existing query object whose type does not match <target>, or if <id> is the
1633 // active query object name for any query type, the error INVALID_OPERATION is
1634 // generated.
1635
1636 // Ensure no other queries are active
1637 // NOTE: If other queries than occlusion are supported, we will need to check
1638 // separately that:
1639 // a) The query ID passed is not the current active query for any target/type
1640 // b) There are no active queries for the requested target (and in the case
1641 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1642 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001643
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001644 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001646 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001647 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001648 }
1649
1650 Query *queryObject = context->getQuery(id, true, target);
1651
1652 // check that name was obtained with glGenQueries
1653 if (!queryObject)
1654 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001656 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001657 }
1658
1659 // check for type mismatch
1660 if (queryObject->getType() != target)
1661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001662 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001663 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001664 }
1665
1666 return true;
1667}
1668
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001669bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1670{
1671 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001672 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001675 return false;
1676 }
1677
1678 return ValidateBeginQueryBase(context, target, id);
1679}
1680
1681bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001682{
1683 if (!ValidQueryType(context, target))
1684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001685 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001686 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001687 }
1688
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001689 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001690
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001691 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001693 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001694 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001695 }
1696
Jamie Madill45c785d2014-05-13 14:09:34 -04001697 return true;
1698}
1699
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1701{
1702 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001703 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001704 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001706 return false;
1707 }
1708
1709 return ValidateEndQueryBase(context, target);
1710}
1711
1712bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1713{
1714 if (!context->getExtensions().disjointTimerQuery)
1715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001716 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001717 return false;
1718 }
1719
1720 if (target != GL_TIMESTAMP_EXT)
1721 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001722 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001723 return false;
1724 }
1725
1726 Query *queryObject = context->getQuery(id, true, target);
1727 if (queryObject == nullptr)
1728 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001729 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001730 return false;
1731 }
1732
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001733 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001734 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001735 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736 return false;
1737 }
1738
1739 return true;
1740}
1741
Geoff Lang2186c382016-10-14 10:54:54 -04001742bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001743{
Geoff Lang2186c382016-10-14 10:54:54 -04001744 if (numParams)
1745 {
1746 *numParams = 0;
1747 }
1748
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001749 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1750 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752 return false;
1753 }
1754
1755 switch (pname)
1756 {
1757 case GL_CURRENT_QUERY_EXT:
1758 if (target == GL_TIMESTAMP_EXT)
1759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001760 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001761 return false;
1762 }
1763 break;
1764 case GL_QUERY_COUNTER_BITS_EXT:
1765 if (!context->getExtensions().disjointTimerQuery ||
1766 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1767 {
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 break;
1772 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001773 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001774 return false;
1775 }
1776
Geoff Lang2186c382016-10-14 10:54:54 -04001777 if (numParams)
1778 {
1779 // All queries return only one value
1780 *numParams = 1;
1781 }
1782
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001783 return true;
1784}
1785
1786bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1787{
1788 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001789 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001790 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001791 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001792 return false;
1793 }
1794
Geoff Lang2186c382016-10-14 10:54:54 -04001795 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001796}
1797
Geoff Lang2186c382016-10-14 10:54:54 -04001798bool ValidateGetQueryivRobustANGLE(Context *context,
1799 GLenum target,
1800 GLenum pname,
1801 GLsizei bufSize,
1802 GLsizei *length,
1803 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001804{
Geoff Lang2186c382016-10-14 10:54:54 -04001805 if (!ValidateRobustEntryPoint(context, bufSize))
1806 {
1807 return false;
1808 }
1809
Brandon Jonesd1049182018-03-28 10:02:20 -07001810 GLsizei numParams = 0;
1811
1812 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001813 {
1814 return false;
1815 }
1816
Brandon Jonesd1049182018-03-28 10:02:20 -07001817 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001818 {
1819 return false;
1820 }
1821
Brandon Jonesd1049182018-03-28 10:02:20 -07001822 SetRobustLengthParam(length, numParams);
1823
Geoff Lang2186c382016-10-14 10:54:54 -04001824 return true;
1825}
1826
1827bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1828{
1829 if (numParams)
1830 {
1831 *numParams = 0;
1832 }
1833
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001834 Query *queryObject = context->getQuery(id, false, GL_NONE);
1835
1836 if (!queryObject)
1837 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001838 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001839 return false;
1840 }
1841
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001842 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001843 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001845 return false;
1846 }
1847
1848 switch (pname)
1849 {
1850 case GL_QUERY_RESULT_EXT:
1851 case GL_QUERY_RESULT_AVAILABLE_EXT:
1852 break;
1853
1854 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001855 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001856 return false;
1857 }
1858
Geoff Lang2186c382016-10-14 10:54:54 -04001859 if (numParams)
1860 {
1861 *numParams = 1;
1862 }
1863
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001864 return true;
1865}
1866
1867bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1868{
1869 if (!context->getExtensions().disjointTimerQuery)
1870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001871 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001872 return false;
1873 }
Geoff Lang2186c382016-10-14 10:54:54 -04001874 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1875}
1876
1877bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1878 GLuint id,
1879 GLenum pname,
1880 GLsizei bufSize,
1881 GLsizei *length,
1882 GLint *params)
1883{
1884 if (!context->getExtensions().disjointTimerQuery)
1885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001886 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001887 return false;
1888 }
1889
1890 if (!ValidateRobustEntryPoint(context, bufSize))
1891 {
1892 return false;
1893 }
1894
Brandon Jonesd1049182018-03-28 10:02:20 -07001895 GLsizei numParams = 0;
1896
1897 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001898 {
1899 return false;
1900 }
1901
Brandon Jonesd1049182018-03-28 10:02:20 -07001902 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001903 {
1904 return false;
1905 }
1906
Brandon Jonesd1049182018-03-28 10:02:20 -07001907 SetRobustLengthParam(length, numParams);
1908
Geoff Lang2186c382016-10-14 10:54:54 -04001909 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001910}
1911
1912bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1913{
1914 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001915 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001917 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001918 return false;
1919 }
Geoff Lang2186c382016-10-14 10:54:54 -04001920 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1921}
1922
1923bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1924 GLuint id,
1925 GLenum pname,
1926 GLsizei bufSize,
1927 GLsizei *length,
1928 GLuint *params)
1929{
1930 if (!context->getExtensions().disjointTimerQuery &&
1931 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1932 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001934 return false;
1935 }
1936
1937 if (!ValidateRobustEntryPoint(context, bufSize))
1938 {
1939 return false;
1940 }
1941
Brandon Jonesd1049182018-03-28 10:02:20 -07001942 GLsizei numParams = 0;
1943
1944 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001945 {
1946 return false;
1947 }
1948
Brandon Jonesd1049182018-03-28 10:02:20 -07001949 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001950 {
1951 return false;
1952 }
1953
Brandon Jonesd1049182018-03-28 10:02:20 -07001954 SetRobustLengthParam(length, numParams);
1955
Geoff Lang2186c382016-10-14 10:54:54 -04001956 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001957}
1958
1959bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1960{
1961 if (!context->getExtensions().disjointTimerQuery)
1962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001963 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001964 return false;
1965 }
Geoff Lang2186c382016-10-14 10:54:54 -04001966 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1967}
1968
1969bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1970 GLuint id,
1971 GLenum pname,
1972 GLsizei bufSize,
1973 GLsizei *length,
1974 GLint64 *params)
1975{
1976 if (!context->getExtensions().disjointTimerQuery)
1977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001978 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001979 return false;
1980 }
1981
1982 if (!ValidateRobustEntryPoint(context, bufSize))
1983 {
1984 return false;
1985 }
1986
Brandon Jonesd1049182018-03-28 10:02:20 -07001987 GLsizei numParams = 0;
1988
1989 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001990 {
1991 return false;
1992 }
1993
Brandon Jonesd1049182018-03-28 10:02:20 -07001994 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001995 {
1996 return false;
1997 }
1998
Brandon Jonesd1049182018-03-28 10:02:20 -07001999 SetRobustLengthParam(length, numParams);
2000
Geoff Lang2186c382016-10-14 10:54:54 -04002001 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002002}
2003
2004bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2005{
2006 if (!context->getExtensions().disjointTimerQuery)
2007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002008 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002009 return false;
2010 }
Geoff Lang2186c382016-10-14 10:54:54 -04002011 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2012}
2013
2014bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2015 GLuint id,
2016 GLenum pname,
2017 GLsizei bufSize,
2018 GLsizei *length,
2019 GLuint64 *params)
2020{
2021 if (!context->getExtensions().disjointTimerQuery)
2022 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002023 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002024 return false;
2025 }
2026
2027 if (!ValidateRobustEntryPoint(context, bufSize))
2028 {
2029 return false;
2030 }
2031
Brandon Jonesd1049182018-03-28 10:02:20 -07002032 GLsizei numParams = 0;
2033
2034 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002035 {
2036 return false;
2037 }
2038
Brandon Jonesd1049182018-03-28 10:02:20 -07002039 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002040 {
2041 return false;
2042 }
2043
Brandon Jonesd1049182018-03-28 10:02:20 -07002044 SetRobustLengthParam(length, numParams);
2045
Geoff Lang2186c382016-10-14 10:54:54 -04002046 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002047}
2048
Jamie Madill5b772312018-03-08 20:28:32 -05002049bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002050 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002051 GLint location,
2052 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002053 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002054{
Jiajia Qin5451d532017-11-16 17:16:34 +08002055 // TODO(Jiajia): Add image uniform check in future.
2056 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002057 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002058 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002059 return false;
2060 }
2061
Jiajia Qin5451d532017-11-16 17:16:34 +08002062 if (!program)
2063 {
2064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2065 return false;
2066 }
2067
2068 if (!program->isLinked())
2069 {
2070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2071 return false;
2072 }
2073
2074 if (location == -1)
2075 {
2076 // Silently ignore the uniform command
2077 return false;
2078 }
2079
2080 const auto &uniformLocations = program->getUniformLocations();
2081 size_t castedLocation = static_cast<size_t>(location);
2082 if (castedLocation >= uniformLocations.size())
2083 {
2084 context->handleError(InvalidOperation() << "Invalid uniform location");
2085 return false;
2086 }
2087
2088 const auto &uniformLocation = uniformLocations[castedLocation];
2089 if (uniformLocation.ignored)
2090 {
2091 // Silently ignore the uniform command
2092 return false;
2093 }
2094
2095 if (!uniformLocation.used())
2096 {
2097 context->handleError(InvalidOperation());
2098 return false;
2099 }
2100
2101 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2102
2103 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2104 if (!uniform.isArray() && count > 1)
2105 {
2106 context->handleError(InvalidOperation());
2107 return false;
2108 }
2109
2110 *uniformOut = &uniform;
2111 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002112}
2113
Jamie Madill5b772312018-03-08 20:28:32 -05002114bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002115 GLenum uniformType,
2116 GLsizei count,
2117 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002118{
Jiajia Qin5451d532017-11-16 17:16:34 +08002119 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2120 // It is compatible with INT or BOOL.
2121 // Do these cheap tests first, for a little extra speed.
2122 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002123 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002124 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002125 }
2126
Jiajia Qin5451d532017-11-16 17:16:34 +08002127 if (IsSamplerType(uniformType))
2128 {
2129 // Check that the values are in range.
2130 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2131 for (GLsizei i = 0; i < count; ++i)
2132 {
2133 if (value[i] < 0 || value[i] >= max)
2134 {
2135 context->handleError(InvalidValue() << "sampler uniform value out of range");
2136 return false;
2137 }
2138 }
2139 return true;
2140 }
2141
2142 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2143 return false;
2144}
2145
Jamie Madill5b772312018-03-08 20:28:32 -05002146bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002147{
2148 // Check that the value type is compatible with uniform type.
2149 // Do the cheaper test first, for a little extra speed.
2150 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2151 {
2152 return true;
2153 }
2154
2155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2156 return false;
2157}
2158
Jamie Madill5b772312018-03-08 20:28:32 -05002159bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002160{
2161 // Check that the value type is compatible with uniform type.
2162 if (valueType == uniformType)
2163 {
2164 return true;
2165 }
2166
2167 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2168 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002169}
2170
Jamie Madill5b772312018-03-08 20:28:32 -05002171bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002172{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002173 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002174 gl::Program *programObject = context->getGLState().getProgram();
2175 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2176 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002177}
2178
Jamie Madill5b772312018-03-08 20:28:32 -05002179bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002180{
2181 const LinkedUniform *uniform = nullptr;
2182 gl::Program *programObject = context->getGLState().getProgram();
2183 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2184 ValidateUniform1ivValue(context, uniform->type, count, value);
2185}
2186
Jamie Madill5b772312018-03-08 20:28:32 -05002187bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002188 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002189 GLint location,
2190 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002191 GLboolean transpose)
2192{
Geoff Lang92019432017-11-20 13:09:34 -05002193 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002195 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002196 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002197 }
2198
Jamie Madill62d31cb2015-09-11 13:25:51 -04002199 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002200 gl::Program *programObject = context->getGLState().getProgram();
2201 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2202 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002203}
2204
Jamie Madill5b772312018-03-08 20:28:32 -05002205bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002206{
2207 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002209 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002210 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002211 }
2212
Jamie Madill0af26e12015-03-05 19:54:33 -05002213 const Caps &caps = context->getCaps();
2214
Jamie Madill893ab082014-05-16 16:56:10 -04002215 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2216 {
2217 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2218
Jamie Madill0af26e12015-03-05 19:54:33 -05002219 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002221 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002222 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002223 }
2224 }
2225
2226 switch (pname)
2227 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002228 case GL_TEXTURE_BINDING_2D:
2229 case GL_TEXTURE_BINDING_CUBE_MAP:
2230 case GL_TEXTURE_BINDING_3D:
2231 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002232 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002233 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002234 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2235 if (!context->getExtensions().textureRectangle)
2236 {
2237 context->handleError(InvalidEnum()
2238 << "ANGLE_texture_rectangle extension not present");
2239 return false;
2240 }
2241 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002242 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2243 if (!context->getExtensions().eglStreamConsumerExternal &&
2244 !context->getExtensions().eglImageExternal)
2245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002246 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2247 "nor GL_OES_EGL_image_external "
2248 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002249 return false;
2250 }
2251 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002252
He Yunchaoced53ae2016-11-29 15:00:51 +08002253 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2254 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002255 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002256 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2257 ASSERT(readFramebuffer);
2258
Jamie Madill427064d2018-04-13 16:20:34 -04002259 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002260 {
Geoff Langb1196682014-07-23 13:47:29 -04002261 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002262 }
2263
Jamie Madille98b1b52018-03-08 09:47:23 -05002264 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002265 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002266 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002267 return false;
2268 }
2269
Jamie Madille98b1b52018-03-08 09:47:23 -05002270 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002271 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002273 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002274 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002275 }
2276 }
2277 break;
2278
He Yunchaoced53ae2016-11-29 15:00:51 +08002279 default:
2280 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002281 }
2282
2283 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002284 if (*numParams == 0)
2285 {
2286 return false;
2287 }
2288
2289 return true;
2290}
2291
Brandon Jonesd1049182018-03-28 10:02:20 -07002292bool ValidateGetBooleanvRobustANGLE(Context *context,
2293 GLenum pname,
2294 GLsizei bufSize,
2295 GLsizei *length,
2296 GLboolean *params)
2297{
2298 GLenum nativeType;
2299 unsigned int numParams = 0;
2300
2301 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2302 {
2303 return false;
2304 }
2305
2306 SetRobustLengthParam(length, numParams);
2307
2308 return true;
2309}
2310
2311bool ValidateGetFloatvRobustANGLE(Context *context,
2312 GLenum pname,
2313 GLsizei bufSize,
2314 GLsizei *length,
2315 GLfloat *params)
2316{
2317 GLenum nativeType;
2318 unsigned int numParams = 0;
2319
2320 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2321 {
2322 return false;
2323 }
2324
2325 SetRobustLengthParam(length, numParams);
2326
2327 return true;
2328}
2329
2330bool ValidateGetIntegervRobustANGLE(Context *context,
2331 GLenum pname,
2332 GLsizei bufSize,
2333 GLsizei *length,
2334 GLint *data)
2335{
2336 GLenum nativeType;
2337 unsigned int numParams = 0;
2338
2339 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2340 {
2341 return false;
2342 }
2343
2344 SetRobustLengthParam(length, numParams);
2345
2346 return true;
2347}
2348
2349bool ValidateGetInteger64vRobustANGLE(Context *context,
2350 GLenum pname,
2351 GLsizei bufSize,
2352 GLsizei *length,
2353 GLint64 *data)
2354{
2355 GLenum nativeType;
2356 unsigned int numParams = 0;
2357
2358 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2359 {
2360 return false;
2361 }
2362
2363 if (nativeType == GL_INT_64_ANGLEX)
2364 {
2365 CastStateValues(context, nativeType, pname, numParams, data);
2366 return false;
2367 }
2368
2369 SetRobustLengthParam(length, numParams);
2370 return true;
2371}
2372
Jamie Madill5b772312018-03-08 20:28:32 -05002373bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002374 GLenum pname,
2375 GLsizei bufSize,
2376 GLenum *nativeType,
2377 unsigned int *numParams)
2378{
2379 if (!ValidateRobustEntryPoint(context, bufSize))
2380 {
2381 return false;
2382 }
2383
2384 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2385 {
2386 return false;
2387 }
2388
2389 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002390 {
2391 return false;
2392 }
2393
2394 return true;
2395}
2396
Jamie Madill5b772312018-03-08 20:28:32 -05002397bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002398 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002399 GLint level,
2400 GLenum internalformat,
2401 bool isSubImage,
2402 GLint xoffset,
2403 GLint yoffset,
2404 GLint zoffset,
2405 GLint x,
2406 GLint y,
2407 GLsizei width,
2408 GLsizei height,
2409 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002410 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002411{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002412 TextureType texType = TextureTargetToType(target);
2413
Brandon Jones6cad5662017-06-14 13:25:13 -07002414 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002415 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002416 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2417 return false;
2418 }
2419
2420 if (width < 0 || height < 0)
2421 {
2422 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002423 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 }
2425
He Yunchaoced53ae2016-11-29 15:00:51 +08002426 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2427 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002429 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002430 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002431 }
2432
2433 if (border != 0)
2434 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002435 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002436 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002437 }
2438
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002439 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002440 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002441 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002442 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002443 }
2444
Jamie Madille98b1b52018-03-08 09:47:23 -05002445 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002446 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002447 if (!ValidateFramebufferComplete(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
Jamie Madille98b1b52018-03-08 09:47:23 -05002452 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002453 {
Geoff Langb1196682014-07-23 13:47:29 -04002454 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002455 }
2456
Martin Radev138064f2016-07-15 12:03:41 +03002457 if (readFramebuffer->getReadBufferState() == GL_NONE)
2458 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002460 return false;
2461 }
2462
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002463 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2464 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002465 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002466 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002467 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2468 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002470 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002471 return false;
2472 }
2473
Martin Radev04e2c3b2017-07-27 16:54:35 +03002474 // ANGLE_multiview spec, Revision 1:
2475 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2476 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2477 // is not NONE.
2478 if (source->getMultiviewLayout() != GL_NONE)
2479 {
2480 context->handleError(InvalidFramebufferOperation()
2481 << "The active read framebuffer object has multiview attachments.");
2482 return false;
2483 }
2484
Geoff Langaae65a42014-05-26 12:43:44 -04002485 const gl::Caps &caps = context->getCaps();
2486
Geoff Langaae65a42014-05-26 12:43:44 -04002487 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002488 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002489 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002490 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002491 maxDimension = caps.max2DTextureSize;
2492 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002493
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002494 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002495 maxDimension = caps.maxCubeMapTextureSize;
2496 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002497
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002498 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002499 maxDimension = caps.maxRectangleTextureSize;
2500 break;
2501
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002502 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002503 maxDimension = caps.max2DTextureSize;
2504 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002505
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002506 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002507 maxDimension = caps.max3DTextureSize;
2508 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002509
He Yunchaoced53ae2016-11-29 15:00:51 +08002510 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002511 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002512 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 }
2514
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002515 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002516 if (!texture)
2517 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002518 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002519 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002520 }
2521
Geoff Lang69cce582015-09-17 13:20:36 -04002522 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002524 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002525 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002526 }
2527
Geoff Langca271392017-04-05 12:30:00 -04002528 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002529 isSubImage ? *texture->getFormat(target, level).info
2530 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002531
Geoff Lang966c9402017-04-18 12:38:27 -04002532 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002534 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002535 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002536 }
2537
2538 if (isSubImage)
2539 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002540 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2541 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2542 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002544 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002545 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002546 }
2547 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002548 else
2549 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002550 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002551 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002552 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002553 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002554 }
2555
Geoff Langeb66a6e2016-10-31 13:06:12 -04002556 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002557 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002558 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002559 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002560 }
2561
2562 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002563 if (static_cast<int>(width) > maxLevelDimension ||
2564 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002565 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002566 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002567 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002568 }
2569 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002570
Jamie Madill0c8abca2016-07-22 20:21:26 -04002571 if (textureFormatOut)
2572 {
2573 *textureFormatOut = texture->getFormat(target, level);
2574 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002575
2576 // Detect texture copying feedback loops for WebGL.
2577 if (context->getExtensions().webglCompatibility)
2578 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002579 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002580 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002582 return false;
2583 }
2584 }
2585
Jamie Madill560a8d82014-05-21 13:06:20 -04002586 return true;
2587}
2588
Jamie Madill5b772312018-03-08 20:28:32 -05002589bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002590{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002591 const Extensions &extensions = context->getExtensions();
2592
Jamie Madill1aeb1312014-06-20 13:21:25 -04002593 switch (mode)
2594 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002595 case GL_POINTS:
2596 case GL_LINES:
2597 case GL_LINE_LOOP:
2598 case GL_LINE_STRIP:
2599 case GL_TRIANGLES:
2600 case GL_TRIANGLE_STRIP:
2601 case GL_TRIANGLE_FAN:
2602 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002603
2604 case GL_LINES_ADJACENCY_EXT:
2605 case GL_LINE_STRIP_ADJACENCY_EXT:
2606 case GL_TRIANGLES_ADJACENCY_EXT:
2607 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2608 if (!extensions.geometryShader)
2609 {
2610 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2611 return false;
2612 }
2613 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002614 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002615 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002616 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002617 }
2618
Jamie Madill250d33f2014-06-06 17:09:03 -04002619 if (count < 0)
2620 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002621 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002622 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002623 }
2624
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002625 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002626
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002627 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2628 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2629 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2630 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002631 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002632 // Check for mapped buffers
2633 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002634 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002635 {
2636 context->handleError(InvalidOperation());
2637 return false;
2638 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002639 }
2640
Jamie Madillcbcde722017-01-06 14:50:00 -05002641 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2642 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002643 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002644 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002645 {
Ken Russellb9f92502018-01-27 19:00:26 -08002646 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002647 const FramebufferAttachment *dsAttachment =
2648 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002649 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2650 ASSERT(stencilBits <= 8);
2651
Jinyoung Hur85769f02015-10-20 17:08:44 -04002652 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002653 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002654 {
Ken Russellb9f92502018-01-27 19:00:26 -08002655 GLuint maxStencilValue = (1 << stencilBits) - 1;
2656
2657 bool differentRefs =
2658 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2659 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2660 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2661 (depthStencilState.stencilBackWritemask & maxStencilValue);
2662 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2663 (depthStencilState.stencilBackMask & maxStencilValue);
2664
2665 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002666 {
Ken Russellb9f92502018-01-27 19:00:26 -08002667 if (!extensions.webglCompatibility)
2668 {
2669 ERR() << "This ANGLE implementation does not support separate front/back "
2670 "stencil writemasks, reference values, or stencil mask values.";
2671 }
2672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2673 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002674 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002675 }
Jamie Madillac528012014-06-20 13:21:23 -04002676 }
2677
Jamie Madill427064d2018-04-13 16:20:34 -04002678 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002679 {
Geoff Langb1196682014-07-23 13:47:29 -04002680 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002681 }
2682
Geoff Lang7dd2e102014-11-10 15:19:26 -05002683 gl::Program *program = state.getProgram();
2684 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002685 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002686 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002687 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002688 }
2689
Yunchao Hecddcb592017-11-13 15:27:35 +08002690 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2691 // vertex shader stage or fragment shader stage is a undefined behaviour.
2692 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2693 // produce undefined result.
Jiawei Shao385b3e02018-03-21 09:43:28 +08002694 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2695 !program->hasLinkedShaderStage(ShaderType::Fragment))
Yunchao Hecddcb592017-11-13 15:27:35 +08002696 {
2697 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2698 "vertex shader stage or fragment shader stage.");
2699 return false;
2700 }
2701
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002702 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002704 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002705 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002706 }
2707
Martin Radevffe754b2017-07-31 10:38:07 +03002708 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002709 {
Martin Radevda8e2572017-09-12 17:21:16 +03002710 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002711 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002712 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002713 {
2714 context->handleError(InvalidOperation() << "The number of views in the active program "
2715 "and draw framebuffer does not match.");
2716 return false;
2717 }
Martin Radev7e69f762017-07-27 14:54:13 +03002718
2719 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2720 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2721 framebufferNumViews > 1)
2722 {
2723 context->handleError(InvalidOperation()
2724 << "There is an active transform feedback object "
2725 "when the number of views in the active draw "
2726 "framebuffer is greater than 1.");
2727 return false;
2728 }
Martin Radevffe754b2017-07-31 10:38:07 +03002729
2730 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2731 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2732 {
2733 context->handleError(InvalidOperation() << "There is an active query for target "
2734 "GL_TIME_ELAPSED_EXT when the number of "
2735 "views in the active draw framebuffer is "
2736 "greater than 1.");
2737 return false;
2738 }
Martin Radev7cf61662017-07-26 17:10:53 +03002739 }
2740
Jiawei Shaofccebff2018-03-08 13:51:02 +08002741 // Do geometry shader specific validations
Jiawei Shao385b3e02018-03-21 09:43:28 +08002742 if (program->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shaofccebff2018-03-08 13:51:02 +08002743 {
2744 if (!IsCompatibleDrawModeWithGeometryShader(mode,
2745 program->getGeometryShaderInputPrimitiveType()))
2746 {
2747 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2748 IncompatibleDrawModeAgainstGeometryShader);
2749 return false;
2750 }
2751 }
2752
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002753 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002754 for (unsigned int uniformBlockIndex = 0;
2755 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002756 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002757 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Lingfeng Yang038dd532018-03-29 17:31:52 -07002758 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002759 const OffsetBindingPointer<Buffer> &uniformBuffer =
2760 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002761
Geoff Lang5d124a62015-09-15 13:03:27 -04002762 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002763 {
2764 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002765 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002766 InvalidOperation()
2767 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002768 return false;
2769 }
2770
James Darpinian30b604d2018-03-12 17:26:57 -07002771 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002772 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002773 {
2774 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002775 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002776 InvalidOperation()
2777 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002778 return false;
2779 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002780
2781 if (extensions.webglCompatibility &&
2782 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2783 {
2784 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2785 UniformBufferBoundForTransformFeedback);
2786 return false;
2787 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002788 }
2789
Geoff Lange0cff192017-05-30 13:04:56 -04002790 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002791 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002792 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002793 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2794 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2795 transformFeedbackObject->buffersBoundForOtherUse())
2796 {
2797 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2798 return false;
2799 }
Geoff Lange0cff192017-05-30 13:04:56 -04002800 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002801 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2802 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002804 return false;
2805 }
Geoff Lange0cff192017-05-30 13:04:56 -04002806
Geoff Lang9ab5b822017-05-30 16:19:23 -04002807 // Detect that the vertex shader input types match the attribute types
2808 if (!ValidateVertexShaderAttributeTypeMatch(context))
2809 {
2810 return false;
2811 }
2812
Geoff Lange0cff192017-05-30 13:04:56 -04002813 // Detect that the color buffer types match the fragment shader output types
2814 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2815 {
2816 return false;
2817 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002818 }
2819
Jamie Madill9fdaa492018-02-16 10:52:11 -05002820 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002821}
2822
Jamie Madill5b772312018-03-08 20:28:32 -05002823bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002824 GLenum mode,
2825 GLint first,
2826 GLsizei count,
2827 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002828{
Jamie Madillfd716582014-06-06 17:09:04 -04002829 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002830 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002831 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002832 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002833 }
2834
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002835 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002836 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002837 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002838 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002839 {
James Darpinian30b604d2018-03-12 17:26:57 -07002840 if (curTransformFeedback->getPrimitiveMode() != mode)
2841 {
2842 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2843 // that does not match the current transform feedback object's draw mode (if transform
2844 // feedback
2845 // is active), (3.0.2, section 2.14, pg 86)
2846 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2847 return false;
2848 }
2849
2850 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2851 {
2852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2853 return false;
2854 }
Jamie Madillfd716582014-06-06 17:09:04 -04002855 }
2856
Jiajia Qind9671222016-11-29 16:30:31 +08002857 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002858 {
2859 return false;
2860 }
2861
Corentin Wallez71168a02016-12-19 15:11:18 -08002862 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002863 // - first < 0 has been checked as an error condition.
2864 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002865 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002866 ASSERT(first >= 0);
2867 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002868 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002869 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2870 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2871 {
2872 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2873 return false;
2874 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002875
Jamie Madill9fdaa492018-02-16 10:52:11 -05002876 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2877 {
2878 return false;
2879 }
Jamie Madillfd716582014-06-06 17:09:04 -04002880 }
2881
2882 return true;
2883}
2884
He Yunchaoced53ae2016-11-29 15:00:51 +08002885bool ValidateDrawArraysInstancedANGLE(Context *context,
2886 GLenum mode,
2887 GLint first,
2888 GLsizei count,
2889 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002890{
Geoff Lang63c5a592017-09-27 14:08:16 -04002891 if (!context->getExtensions().instancedArrays)
2892 {
2893 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2894 return false;
2895 }
2896
Corentin Wallez170efbf2017-05-02 13:45:01 -04002897 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002898 {
2899 return false;
2900 }
2901
Corentin Wallez0dc97812017-06-22 14:38:44 -04002902 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002903}
2904
Jamie Madill5b772312018-03-08 20:28:32 -05002905bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002906{
Jamie Madill250d33f2014-06-06 17:09:03 -04002907 switch (type)
2908 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002909 case GL_UNSIGNED_BYTE:
2910 case GL_UNSIGNED_SHORT:
2911 break;
2912 case GL_UNSIGNED_INT:
2913 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002916 return false;
2917 }
2918 break;
2919 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002920 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002921 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002922 }
2923
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002924 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002925
2926 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002927 if (curTransformFeedback && curTransformFeedback->isActive() &&
2928 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002929 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002930 // It is an invalid operation to call DrawElements, DrawRangeElements or
2931 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002932 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002933 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002934 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002935 }
2936
Jiajia Qind9671222016-11-29 16:30:31 +08002937 return true;
2938}
2939
Jamie Madill5b772312018-03-08 20:28:32 -05002940bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002941 GLenum mode,
2942 GLsizei count,
2943 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002944 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002945 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002946{
2947 if (!ValidateDrawElementsBase(context, type))
2948 return false;
2949
2950 const State &state = context->getGLState();
2951
Corentin Wallez170efbf2017-05-02 13:45:01 -04002952 if (!ValidateDrawBase(context, mode, count))
2953 {
2954 return false;
2955 }
2956
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002957 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2958 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2959 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2960 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002961 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002962 // Check for mapped buffers
2963 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002964 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002965 {
2966 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2967 return false;
2968 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002969 }
2970
He Yunchaoced53ae2016-11-29 15:00:51 +08002971 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002972 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002973
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002974 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2975
2976 if (context->getExtensions().webglCompatibility)
2977 {
2978 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2979 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2980 {
2981 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2982 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2983 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002984 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002985 return false;
2986 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002987
2988 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2989 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2990 // error is generated.
2991 if (reinterpret_cast<intptr_t>(indices) < 0)
2992 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002993 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002994 return false;
2995 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002996 }
2997
2998 if (context->getExtensions().webglCompatibility ||
2999 !context->getGLState().areClientArraysEnabled())
3000 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003001 if (!elementArrayBuffer && count > 0)
3002 {
3003 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3004 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3005 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003007 return false;
3008 }
3009 }
3010
Jamie Madill9fdaa492018-02-16 10:52:11 -05003011 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003012 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003013 // This is an application error that would normally result in a crash, but we catch it and
3014 // return an error
3015 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3016 return false;
3017 }
3018
3019 if (count > 0 && elementArrayBuffer)
3020 {
3021 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3022 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3023 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3024 constexpr uint64_t kMaxTypeSize = 8;
3025 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3026 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3027 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3028
3029 uint64_t typeSize = typeBytes;
3030 uint64_t elementCount = static_cast<uint64_t>(count);
3031 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3032
3033 // Doing the multiplication here is overflow-safe
3034 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3035
3036 // The offset can be any value, check for overflows
3037 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3038 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003039 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003040 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3041 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003042 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003043
3044 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3045 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003046 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003047 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3048 return false;
3049 }
3050
3051 ASSERT(isPow2(typeSize) && typeSize > 0);
3052 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3053 {
3054 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003055 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003056 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003057
3058 if (context->getExtensions().webglCompatibility &&
3059 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3060 {
3061 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3062 ElementArrayBufferBoundForTransformFeedback);
3063 return false;
3064 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003065 }
3066
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003067 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003068 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003069 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3070 // access is enabled.
3071 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3072 {
3073 return false;
3074 }
3075 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003076 else if (count == 0)
3077 {
3078 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3079 // count.
3080 if (!ValidateDrawAttribs(context, 0, 0, 0))
3081 {
3082 return false;
3083 }
3084 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003085 else
3086 {
3087 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003088 const DrawCallParams &params = context->getParams<DrawCallParams>();
3089 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3090 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003091
3092 // If we use an index greater than our maximum supported index range, return an error.
3093 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3094 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003095 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003096 {
3097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3098 return false;
3099 }
3100
Jamie Madill6f5444d2018-03-14 10:08:11 -04003101 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3102 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003103 {
3104 return false;
3105 }
3106
3107 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003108 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003109 }
3110
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003111 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003112}
3113
Jamie Madill5b772312018-03-08 20:28:32 -05003114bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003115 GLenum mode,
3116 GLsizei count,
3117 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003118 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003119 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003120{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003121 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003122}
3123
Geoff Lang3edfe032015-09-04 16:38:24 -04003124bool ValidateDrawElementsInstancedANGLE(Context *context,
3125 GLenum mode,
3126 GLsizei count,
3127 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003128 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003129 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003130{
Geoff Lang63c5a592017-09-27 14:08:16 -04003131 if (!context->getExtensions().instancedArrays)
3132 {
3133 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3134 return false;
3135 }
3136
Corentin Wallez170efbf2017-05-02 13:45:01 -04003137 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003138 {
3139 return false;
3140 }
3141
Corentin Wallez0dc97812017-06-22 14:38:44 -04003142 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003143}
3144
He Yunchaoced53ae2016-11-29 15:00:51 +08003145bool ValidateFramebufferTextureBase(Context *context,
3146 GLenum target,
3147 GLenum attachment,
3148 GLuint texture,
3149 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003150{
Geoff Lange8afa902017-09-27 15:00:43 -04003151 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003153 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003154 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003155 }
3156
3157 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003158 {
3159 return false;
3160 }
3161
Jamie Madill55ec3b12014-07-03 10:38:57 -04003162 if (texture != 0)
3163 {
3164 gl::Texture *tex = context->getTexture(texture);
3165
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003166 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003168 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003169 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003170 }
3171
3172 if (level < 0)
3173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003174 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003175 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003176 }
3177 }
3178
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003179 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003180 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003181
Jamie Madill84115c92015-04-23 15:00:07 -04003182 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003183 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003185 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003186 }
3187
3188 return true;
3189}
3190
Geoff Langb1196682014-07-23 13:47:29 -04003191bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003192{
3193 if (program == 0)
3194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003195 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003196 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003197 }
3198
Dian Xiang769769a2015-09-09 15:20:08 -07003199 gl::Program *programObject = GetValidProgram(context, program);
3200 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003201 {
3202 return false;
3203 }
3204
Jamie Madill0063c512014-08-25 15:47:53 -04003205 if (!programObject || !programObject->isLinked())
3206 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003207 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003208 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003209 }
3210
Geoff Lang7dd2e102014-11-10 15:19:26 -05003211 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003213 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003214 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003215 }
3216
Jamie Madill0063c512014-08-25 15:47:53 -04003217 return true;
3218}
3219
Geoff Langf41d0ee2016-10-07 13:04:23 -04003220static bool ValidateSizedGetUniform(Context *context,
3221 GLuint program,
3222 GLint location,
3223 GLsizei bufSize,
3224 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003225{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003226 if (length)
3227 {
3228 *length = 0;
3229 }
3230
Jamie Madill78f41802014-08-25 15:47:55 -04003231 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003232 {
Jamie Madill78f41802014-08-25 15:47:55 -04003233 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003234 }
3235
Geoff Langf41d0ee2016-10-07 13:04:23 -04003236 if (bufSize < 0)
3237 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003238 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003239 return false;
3240 }
3241
Jamie Madilla502c742014-08-28 17:19:13 -04003242 gl::Program *programObject = context->getProgram(program);
3243 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003244
Jamie Madill78f41802014-08-25 15:47:55 -04003245 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003246 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003247 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003248 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003249 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003251 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003252 }
3253
Geoff Langf41d0ee2016-10-07 13:04:23 -04003254 if (length)
3255 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003256 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003257 }
3258
Jamie Madill0063c512014-08-25 15:47:53 -04003259 return true;
3260}
3261
He Yunchaoced53ae2016-11-29 15:00:51 +08003262bool ValidateGetnUniformfvEXT(Context *context,
3263 GLuint program,
3264 GLint location,
3265 GLsizei bufSize,
3266 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003267{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003268 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003269}
3270
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003271bool ValidateGetnUniformfvRobustANGLE(Context *context,
3272 GLuint program,
3273 GLint location,
3274 GLsizei bufSize,
3275 GLsizei *length,
3276 GLfloat *params)
3277{
3278 UNIMPLEMENTED();
3279 return false;
3280}
3281
He Yunchaoced53ae2016-11-29 15:00:51 +08003282bool ValidateGetnUniformivEXT(Context *context,
3283 GLuint program,
3284 GLint location,
3285 GLsizei bufSize,
3286 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003287{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003288 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3289}
3290
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003291bool ValidateGetnUniformivRobustANGLE(Context *context,
3292 GLuint program,
3293 GLint location,
3294 GLsizei bufSize,
3295 GLsizei *length,
3296 GLint *params)
3297{
3298 UNIMPLEMENTED();
3299 return false;
3300}
3301
3302bool ValidateGetnUniformuivRobustANGLE(Context *context,
3303 GLuint program,
3304 GLint location,
3305 GLsizei bufSize,
3306 GLsizei *length,
3307 GLuint *params)
3308{
3309 UNIMPLEMENTED();
3310 return false;
3311}
3312
Geoff Langf41d0ee2016-10-07 13:04:23 -04003313bool ValidateGetUniformfvRobustANGLE(Context *context,
3314 GLuint program,
3315 GLint location,
3316 GLsizei bufSize,
3317 GLsizei *length,
3318 GLfloat *params)
3319{
3320 if (!ValidateRobustEntryPoint(context, bufSize))
3321 {
3322 return false;
3323 }
3324
Brandon Jonesd1049182018-03-28 10:02:20 -07003325 GLsizei writeLength = 0;
3326
Geoff Langf41d0ee2016-10-07 13:04:23 -04003327 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003328 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3329 {
3330 return false;
3331 }
3332
3333 SetRobustLengthParam(length, writeLength);
3334
3335 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003336}
3337
3338bool ValidateGetUniformivRobustANGLE(Context *context,
3339 GLuint program,
3340 GLint location,
3341 GLsizei bufSize,
3342 GLsizei *length,
3343 GLint *params)
3344{
3345 if (!ValidateRobustEntryPoint(context, bufSize))
3346 {
3347 return false;
3348 }
3349
Brandon Jonesd1049182018-03-28 10:02:20 -07003350 GLsizei writeLength = 0;
3351
Geoff Langf41d0ee2016-10-07 13:04:23 -04003352 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003353 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3354 {
3355 return false;
3356 }
3357
3358 SetRobustLengthParam(length, writeLength);
3359
3360 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003361}
3362
3363bool ValidateGetUniformuivRobustANGLE(Context *context,
3364 GLuint program,
3365 GLint location,
3366 GLsizei bufSize,
3367 GLsizei *length,
3368 GLuint *params)
3369{
3370 if (!ValidateRobustEntryPoint(context, bufSize))
3371 {
3372 return false;
3373 }
3374
3375 if (context->getClientMajorVersion() < 3)
3376 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003377 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003378 return false;
3379 }
3380
Brandon Jonesd1049182018-03-28 10:02:20 -07003381 GLsizei writeLength = 0;
3382
Geoff Langf41d0ee2016-10-07 13:04:23 -04003383 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003384 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3385 {
3386 return false;
3387 }
3388
3389 SetRobustLengthParam(length, writeLength);
3390
3391 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003392}
3393
He Yunchaoced53ae2016-11-29 15:00:51 +08003394bool ValidateDiscardFramebufferBase(Context *context,
3395 GLenum target,
3396 GLsizei numAttachments,
3397 const GLenum *attachments,
3398 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003399{
3400 if (numAttachments < 0)
3401 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003402 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003403 return false;
3404 }
3405
3406 for (GLsizei i = 0; i < numAttachments; ++i)
3407 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003408 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003409 {
3410 if (defaultFramebuffer)
3411 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003412 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003413 return false;
3414 }
3415
3416 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003418 context->handleError(InvalidOperation() << "Requested color attachment is "
3419 "greater than the maximum supported "
3420 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003421 return false;
3422 }
3423 }
3424 else
3425 {
3426 switch (attachments[i])
3427 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003428 case GL_DEPTH_ATTACHMENT:
3429 case GL_STENCIL_ATTACHMENT:
3430 case GL_DEPTH_STENCIL_ATTACHMENT:
3431 if (defaultFramebuffer)
3432 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003433 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3434 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003435 return false;
3436 }
3437 break;
3438 case GL_COLOR:
3439 case GL_DEPTH:
3440 case GL_STENCIL:
3441 if (!defaultFramebuffer)
3442 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003443 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3444 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003445 return false;
3446 }
3447 break;
3448 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003450 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003451 }
3452 }
3453 }
3454
3455 return true;
3456}
3457
Austin Kinross6ee1e782015-05-29 17:05:37 -07003458bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3459{
Jamie Madill007530e2017-12-28 14:27:04 -05003460 if (!context->getExtensions().debugMarker)
3461 {
3462 // The debug marker calls should not set error state
3463 // However, it seems reasonable to set an error state if the extension is not enabled
3464 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3465 return false;
3466 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003467
Jamie Madill007530e2017-12-28 14:27:04 -05003468 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003469 if (length < 0)
3470 {
3471 return false;
3472 }
3473
3474 if (marker == nullptr)
3475 {
3476 return false;
3477 }
3478
3479 return true;
3480}
3481
3482bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3483{
Jamie Madill007530e2017-12-28 14:27:04 -05003484 if (!context->getExtensions().debugMarker)
3485 {
3486 // The debug marker calls should not set error state
3487 // However, it seems reasonable to set an error state if the extension is not enabled
3488 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3489 return false;
3490 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003491
Jamie Madill007530e2017-12-28 14:27:04 -05003492 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003493 if (length < 0)
3494 {
3495 return false;
3496 }
3497
3498 if (length > 0 && marker == nullptr)
3499 {
3500 return false;
3501 }
3502
3503 return true;
3504}
3505
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003506bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003507{
Geoff Langa8406172015-07-21 16:53:39 -04003508 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003510 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003511 return false;
3512 }
3513
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003514 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003515 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003516 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003517 if (!context->getExtensions().eglImage)
3518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003519 context->handleError(InvalidEnum()
3520 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003521 }
3522 break;
3523
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003524 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003525 if (!context->getExtensions().eglImageExternal)
3526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003527 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3528 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003529 }
Geoff Langa8406172015-07-21 16:53:39 -04003530 break;
3531
3532 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003533 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003534 return false;
3535 }
3536
Jamie Madill007530e2017-12-28 14:27:04 -05003537 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3538
Jamie Madill61e16b42017-06-19 11:13:23 -04003539 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003540 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003542 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003543 return false;
3544 }
3545
Jamie Madill007530e2017-12-28 14:27:04 -05003546 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003548 context->handleError(InvalidOperation()
3549 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003550 return false;
3551 }
3552
Geoff Langca271392017-04-05 12:30:00 -04003553 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003554 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003555 if (!textureCaps.texturable)
3556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003557 context->handleError(InvalidOperation()
3558 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003559 return false;
3560 }
3561
Geoff Langdcab33b2015-07-21 13:03:16 -04003562 return true;
3563}
3564
3565bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003566 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003567 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003568{
Geoff Langa8406172015-07-21 16:53:39 -04003569 if (!context->getExtensions().eglImage)
3570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003571 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003572 return false;
3573 }
3574
3575 switch (target)
3576 {
3577 case GL_RENDERBUFFER:
3578 break;
3579
3580 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003581 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003582 return false;
3583 }
3584
Jamie Madill007530e2017-12-28 14:27:04 -05003585 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3586
Jamie Madill61e16b42017-06-19 11:13:23 -04003587 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003588 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003590 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003591 return false;
3592 }
3593
Geoff Langca271392017-04-05 12:30:00 -04003594 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003595 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003596 if (!textureCaps.renderable)
3597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003598 context->handleError(InvalidOperation()
3599 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003600 return false;
3601 }
3602
Geoff Langdcab33b2015-07-21 13:03:16 -04003603 return true;
3604}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003605
3606bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3607{
Geoff Lang36167ab2015-12-07 10:27:14 -05003608 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003609 {
3610 // The default VAO should always exist
3611 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003612 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003613 return false;
3614 }
3615
3616 return true;
3617}
3618
Geoff Langc5629752015-12-07 16:29:04 -05003619bool ValidateProgramBinaryBase(Context *context,
3620 GLuint program,
3621 GLenum binaryFormat,
3622 const void *binary,
3623 GLint length)
3624{
3625 Program *programObject = GetValidProgram(context, program);
3626 if (programObject == nullptr)
3627 {
3628 return false;
3629 }
3630
3631 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3632 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3633 programBinaryFormats.end())
3634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003635 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003636 return false;
3637 }
3638
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003639 if (context->hasActiveTransformFeedback(program))
3640 {
3641 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003642 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3643 "is associated with an active transform "
3644 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003645 return false;
3646 }
3647
Geoff Langc5629752015-12-07 16:29:04 -05003648 return true;
3649}
3650
3651bool ValidateGetProgramBinaryBase(Context *context,
3652 GLuint program,
3653 GLsizei bufSize,
3654 GLsizei *length,
3655 GLenum *binaryFormat,
3656 void *binary)
3657{
3658 Program *programObject = GetValidProgram(context, program);
3659 if (programObject == nullptr)
3660 {
3661 return false;
3662 }
3663
3664 if (!programObject->isLinked())
3665 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003666 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003667 return false;
3668 }
3669
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003670 if (context->getCaps().programBinaryFormats.empty())
3671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003672 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003673 return false;
3674 }
3675
Geoff Langc5629752015-12-07 16:29:04 -05003676 return true;
3677}
Jamie Madillc29968b2016-01-20 11:17:23 -05003678
Jamie Madill5b772312018-03-08 20:28:32 -05003679bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003680{
3681 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003682 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003683 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003684 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3685 return false;
3686 }
3687 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3688 {
3689 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003690 return false;
3691 }
3692
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003693 ASSERT(context->getGLState().getDrawFramebuffer());
3694 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003695 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3696
3697 // This should come first before the check for the default frame buffer
3698 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3699 // rather than INVALID_OPERATION
3700 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3701 {
3702 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3703
3704 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003705 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3706 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003707 {
3708 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003709 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3710 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3711 // 3.1 is still a bit ambiguous about the error, but future specs are
3712 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003713 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003714 return false;
3715 }
3716 else if (bufs[colorAttachment] >= maxColorAttachment)
3717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003718 context->handleError(InvalidOperation()
3719 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003720 return false;
3721 }
3722 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3723 frameBufferId != 0)
3724 {
3725 // INVALID_OPERATION-GL is bound to buffer and ith argument
3726 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003727 context->handleError(InvalidOperation()
3728 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003729 return false;
3730 }
3731 }
3732
3733 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3734 // and n is not 1 or bufs is bound to value other than BACK and NONE
3735 if (frameBufferId == 0)
3736 {
3737 if (n != 1)
3738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003739 context->handleError(InvalidOperation()
3740 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003741 return false;
3742 }
3743
3744 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003746 context->handleError(
3747 InvalidOperation()
3748 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003749 return false;
3750 }
3751 }
3752
3753 return true;
3754}
3755
Geoff Lang496c02d2016-10-20 11:38:11 -07003756bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003757 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003758 GLenum pname,
3759 GLsizei *length,
3760 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003761{
Geoff Lang496c02d2016-10-20 11:38:11 -07003762 if (length)
3763 {
3764 *length = 0;
3765 }
3766
3767 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3768 {
3769 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003770 InvalidOperation()
3771 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003772 return false;
3773 }
3774
Corentin Walleze4477002017-12-01 14:39:58 -05003775 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003776 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003777 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003778 return false;
3779 }
3780
Geoff Lang496c02d2016-10-20 11:38:11 -07003781 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003782 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003783 case GL_BUFFER_MAP_POINTER:
3784 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003785
Geoff Lang496c02d2016-10-20 11:38:11 -07003786 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003787 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003788 return false;
3789 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003790
3791 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3792 // target bound to zero generate an INVALID_OPERATION error."
3793 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003794 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003796 context->handleError(InvalidOperation()
3797 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003798 return false;
3799 }
3800
Geoff Lang496c02d2016-10-20 11:38:11 -07003801 if (length)
3802 {
3803 *length = 1;
3804 }
3805
Olli Etuaho4f667482016-03-30 15:56:35 +03003806 return true;
3807}
3808
Corentin Wallez336129f2017-10-17 15:55:40 -04003809bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003810{
Corentin Walleze4477002017-12-01 14:39:58 -05003811 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003812 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003813 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003814 return false;
3815 }
3816
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003817 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003818
3819 if (buffer == nullptr || !buffer->isMapped())
3820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003821 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003822 return false;
3823 }
3824
3825 return true;
3826}
3827
3828bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003829 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003830 GLintptr offset,
3831 GLsizeiptr length,
3832 GLbitfield access)
3833{
Corentin Walleze4477002017-12-01 14:39:58 -05003834 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003835 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003836 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003837 return false;
3838 }
3839
Brandon Jones6cad5662017-06-14 13:25:13 -07003840 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003841 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003842 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3843 return false;
3844 }
3845
3846 if (length < 0)
3847 {
3848 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003849 return false;
3850 }
3851
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003852 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003853
3854 if (!buffer)
3855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003856 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003857 return false;
3858 }
3859
3860 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003861 CheckedNumeric<size_t> checkedOffset(offset);
3862 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003863
Jamie Madille2e406c2016-06-02 13:04:10 -04003864 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003866 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003867 return false;
3868 }
3869
3870 // Check for invalid bits in the mask
3871 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3872 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3873 GL_MAP_UNSYNCHRONIZED_BIT;
3874
3875 if (access & ~(allAccessBits))
3876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003877 context->handleError(InvalidValue()
3878 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003879 return false;
3880 }
3881
3882 if (length == 0)
3883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003884 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003885 return false;
3886 }
3887
3888 if (buffer->isMapped())
3889 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003890 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003891 return false;
3892 }
3893
3894 // Check for invalid bit combinations
3895 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003897 context->handleError(InvalidOperation()
3898 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003899 return false;
3900 }
3901
3902 GLbitfield writeOnlyBits =
3903 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3904
3905 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3906 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003907 context->handleError(InvalidOperation()
3908 << "Invalid access bits when mapping buffer for reading: 0x"
3909 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003910 return false;
3911 }
3912
3913 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003915 context->handleError(
3916 InvalidOperation()
3917 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003918 return false;
3919 }
Geoff Lang79f71042017-08-14 16:43:43 -04003920
3921 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003922}
3923
3924bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003925 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003926 GLintptr offset,
3927 GLsizeiptr length)
3928{
Brandon Jones6cad5662017-06-14 13:25:13 -07003929 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003931 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3932 return false;
3933 }
3934
3935 if (length < 0)
3936 {
3937 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003938 return false;
3939 }
3940
Corentin Walleze4477002017-12-01 14:39:58 -05003941 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003943 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003944 return false;
3945 }
3946
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003947 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003948
3949 if (buffer == nullptr)
3950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003951 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003952 return false;
3953 }
3954
3955 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003957 context->handleError(InvalidOperation()
3958 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003959 return false;
3960 }
3961
3962 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003963 CheckedNumeric<size_t> checkedOffset(offset);
3964 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003965
Jamie Madille2e406c2016-06-02 13:04:10 -04003966 if (!checkedSize.IsValid() ||
3967 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003969 context->handleError(InvalidValue()
3970 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003971 return false;
3972 }
3973
3974 return true;
3975}
3976
Olli Etuaho41997e72016-03-10 13:38:39 +02003977bool ValidateGenOrDelete(Context *context, GLint n)
3978{
3979 if (n < 0)
3980 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003981 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003982 return false;
3983 }
3984 return true;
3985}
3986
Jamie Madill5b772312018-03-08 20:28:32 -05003987bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003988{
3989 if (!context->getExtensions().robustClientMemory)
3990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003991 context->handleError(InvalidOperation()
3992 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003993 return false;
3994 }
3995
3996 if (bufSize < 0)
3997 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003998 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003999 return false;
4000 }
4001
4002 return true;
4003}
4004
Jamie Madill5b772312018-03-08 20:28:32 -05004005bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004006{
4007 if (bufSize < numParams)
4008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004009 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4010 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004011 return false;
4012 }
4013
4014 return true;
4015}
4016
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004017bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004018 GLenum target,
4019 GLenum attachment,
4020 GLenum pname,
4021 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004022{
Geoff Lange8afa902017-09-27 15:00:43 -04004023 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004025 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004026 return false;
4027 }
4028
4029 int clientVersion = context->getClientMajorVersion();
4030
4031 switch (pname)
4032 {
4033 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4034 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4035 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4036 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4037 break;
4038
Martin Radeve5285d22017-07-14 16:23:53 +03004039 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4040 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4041 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4042 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4043 if (clientVersion < 3 || !context->getExtensions().multiview)
4044 {
4045 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4046 return false;
4047 }
4048 break;
4049
Geoff Langff5b2d52016-09-07 11:32:23 -04004050 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4051 if (clientVersion < 3 && !context->getExtensions().sRGB)
4052 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004053 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004054 return false;
4055 }
4056 break;
4057
4058 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4059 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4060 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4061 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4062 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4063 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4064 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4065 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4066 if (clientVersion < 3)
4067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004068 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004069 return false;
4070 }
4071 break;
4072
4073 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004074 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004075 return false;
4076 }
4077
4078 // Determine if the attachment is a valid enum
4079 switch (attachment)
4080 {
4081 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004082 case GL_DEPTH:
4083 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004084 if (clientVersion < 3)
4085 {
Geoff Langfa125c92017-10-24 13:01:46 -04004086 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004087 return false;
4088 }
4089 break;
4090
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004091 case GL_DEPTH_STENCIL_ATTACHMENT:
4092 if (clientVersion < 3 && !context->isWebGL1())
4093 {
4094 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4095 return false;
4096 }
4097 break;
4098
Geoff Langfa125c92017-10-24 13:01:46 -04004099 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004100 case GL_DEPTH_ATTACHMENT:
4101 case GL_STENCIL_ATTACHMENT:
4102 break;
4103
4104 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004105 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4106 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004107 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4108 {
Geoff Langfa125c92017-10-24 13:01:46 -04004109 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004110 return false;
4111 }
4112 break;
4113 }
4114
4115 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4116 ASSERT(framebuffer);
4117
4118 if (framebuffer->id() == 0)
4119 {
4120 if (clientVersion < 3)
4121 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004123 return false;
4124 }
4125
4126 switch (attachment)
4127 {
4128 case GL_BACK:
4129 case GL_DEPTH:
4130 case GL_STENCIL:
4131 break;
4132
4133 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004135 return false;
4136 }
4137 }
4138 else
4139 {
4140 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4141 {
4142 // Valid attachment query
4143 }
4144 else
4145 {
4146 switch (attachment)
4147 {
4148 case GL_DEPTH_ATTACHMENT:
4149 case GL_STENCIL_ATTACHMENT:
4150 break;
4151
4152 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004153 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004155 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004156 return false;
4157 }
4158 break;
4159
4160 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004162 return false;
4163 }
4164 }
4165 }
4166
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004167 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004168 if (attachmentObject)
4169 {
4170 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4171 attachmentObject->type() == GL_TEXTURE ||
4172 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4173
4174 switch (pname)
4175 {
4176 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4177 if (attachmentObject->type() != GL_RENDERBUFFER &&
4178 attachmentObject->type() != GL_TEXTURE)
4179 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004181 return false;
4182 }
4183 break;
4184
4185 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4186 if (attachmentObject->type() != GL_TEXTURE)
4187 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004188 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004189 return false;
4190 }
4191 break;
4192
4193 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4194 if (attachmentObject->type() != GL_TEXTURE)
4195 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004197 return false;
4198 }
4199 break;
4200
4201 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4202 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4203 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004204 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004205 return false;
4206 }
4207 break;
4208
4209 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4210 if (attachmentObject->type() != GL_TEXTURE)
4211 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004212 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004213 return false;
4214 }
4215 break;
4216
4217 default:
4218 break;
4219 }
4220 }
4221 else
4222 {
4223 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4224 // is NONE, then querying any other pname will generate INVALID_ENUM.
4225
4226 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4227 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4228 // INVALID_OPERATION for all other pnames
4229
4230 switch (pname)
4231 {
4232 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4233 break;
4234
4235 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4236 if (clientVersion < 3)
4237 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004238 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004239 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004240 return false;
4241 }
4242 break;
4243
4244 default:
4245 if (clientVersion < 3)
4246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004247 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004248 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004249 return false;
4250 }
4251 else
4252 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004253 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004254 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004255 return false;
4256 }
4257 }
4258 }
4259
Martin Radeve5285d22017-07-14 16:23:53 +03004260 if (numParams)
4261 {
4262 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4263 {
4264 // Only when the viewport offsets are queried we can have a varying number of output
4265 // parameters.
4266 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4267 *numParams = numViews * 2;
4268 }
4269 else
4270 {
4271 // For all other queries we can have only one output parameter.
4272 *numParams = 1;
4273 }
4274 }
4275
Geoff Langff5b2d52016-09-07 11:32:23 -04004276 return true;
4277}
4278
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004279bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004280 GLenum target,
4281 GLenum attachment,
4282 GLenum pname,
4283 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004284 GLsizei *length,
4285 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004286{
4287 if (!ValidateRobustEntryPoint(context, bufSize))
4288 {
4289 return false;
4290 }
4291
Brandon Jonesd1049182018-03-28 10:02:20 -07004292 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004293 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004294 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004295 {
4296 return false;
4297 }
4298
Brandon Jonesd1049182018-03-28 10:02:20 -07004299 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004300 {
4301 return false;
4302 }
4303
Brandon Jonesd1049182018-03-28 10:02:20 -07004304 SetRobustLengthParam(length, numParams);
4305
Geoff Langff5b2d52016-09-07 11:32:23 -04004306 return true;
4307}
4308
Jamie Madill5b772312018-03-08 20:28:32 -05004309bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004310 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004311 GLenum pname,
4312 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004313 GLsizei *length,
4314 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004315{
4316 if (!ValidateRobustEntryPoint(context, bufSize))
4317 {
4318 return false;
4319 }
4320
Brandon Jonesd1049182018-03-28 10:02:20 -07004321 GLsizei numParams = 0;
4322
4323 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004324 {
4325 return false;
4326 }
4327
Brandon Jonesd1049182018-03-28 10:02:20 -07004328 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004329 {
4330 return false;
4331 }
4332
Brandon Jonesd1049182018-03-28 10:02:20 -07004333 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004334 return true;
4335}
4336
Jamie Madill5b772312018-03-08 20:28:32 -05004337bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004338 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004339 GLenum pname,
4340 GLsizei bufSize,
4341 GLsizei *length,
4342 GLint64 *params)
4343{
Brandon Jonesd1049182018-03-28 10:02:20 -07004344 GLsizei numParams = 0;
4345
Geoff Langebebe1c2016-10-14 12:01:31 -04004346 if (!ValidateRobustEntryPoint(context, bufSize))
4347 {
4348 return false;
4349 }
4350
Brandon Jonesd1049182018-03-28 10:02:20 -07004351 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004352 {
4353 return false;
4354 }
4355
Brandon Jonesd1049182018-03-28 10:02:20 -07004356 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004357 {
4358 return false;
4359 }
4360
Brandon Jonesd1049182018-03-28 10:02:20 -07004361 SetRobustLengthParam(length, numParams);
4362
Geoff Langff5b2d52016-09-07 11:32:23 -04004363 return true;
4364}
4365
Jamie Madill5b772312018-03-08 20:28:32 -05004366bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004367{
4368 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004369 if (numParams)
4370 {
4371 *numParams = 1;
4372 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004373
4374 Program *programObject = GetValidProgram(context, program);
4375 if (!programObject)
4376 {
4377 return false;
4378 }
4379
4380 switch (pname)
4381 {
4382 case GL_DELETE_STATUS:
4383 case GL_LINK_STATUS:
4384 case GL_VALIDATE_STATUS:
4385 case GL_INFO_LOG_LENGTH:
4386 case GL_ATTACHED_SHADERS:
4387 case GL_ACTIVE_ATTRIBUTES:
4388 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4389 case GL_ACTIVE_UNIFORMS:
4390 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4391 break;
4392
4393 case GL_PROGRAM_BINARY_LENGTH:
4394 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004396 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4397 "requires GL_OES_get_program_binary or "
4398 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004399 return false;
4400 }
4401 break;
4402
4403 case GL_ACTIVE_UNIFORM_BLOCKS:
4404 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4405 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4406 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4407 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4408 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4409 if (context->getClientMajorVersion() < 3)
4410 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004411 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004412 return false;
4413 }
4414 break;
4415
Yunchao He61afff12017-03-14 15:34:03 +08004416 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004417 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004418 if (context->getClientVersion() < Version(3, 1))
4419 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004420 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004421 return false;
4422 }
4423 break;
4424
Jiawei Shao6ae51612018-02-23 14:03:25 +08004425 case GL_COMPUTE_WORK_GROUP_SIZE:
4426 if (context->getClientVersion() < Version(3, 1))
4427 {
4428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4429 return false;
4430 }
4431
4432 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4433 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4434 // program which has not been linked successfully, or which does not contain objects to
4435 // form a compute shader.
4436 if (!programObject->isLinked())
4437 {
4438 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4439 return false;
4440 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004441 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004442 {
4443 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4444 return false;
4445 }
4446 break;
4447
Jiawei Shao447bfac2018-03-14 14:23:40 +08004448 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4449 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4450 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4451 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4452 if (!context->getExtensions().geometryShader)
4453 {
4454 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4455 return false;
4456 }
4457
4458 // [EXT_geometry_shader] Chapter 7.12
4459 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4460 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4461 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4462 // successfully, or which does not contain objects to form a geometry shader.
4463 if (!programObject->isLinked())
4464 {
4465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4466 return false;
4467 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004468 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004469 {
4470 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4471 return false;
4472 }
4473 break;
4474
Geoff Langff5b2d52016-09-07 11:32:23 -04004475 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004476 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004477 return false;
4478 }
4479
4480 return true;
4481}
4482
4483bool ValidateGetProgramivRobustANGLE(Context *context,
4484 GLuint program,
4485 GLenum pname,
4486 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004487 GLsizei *length,
4488 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004489{
4490 if (!ValidateRobustEntryPoint(context, bufSize))
4491 {
4492 return false;
4493 }
4494
Brandon Jonesd1049182018-03-28 10:02:20 -07004495 GLsizei numParams = 0;
4496
4497 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004498 {
4499 return false;
4500 }
4501
Brandon Jonesd1049182018-03-28 10:02:20 -07004502 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004503 {
4504 return false;
4505 }
4506
Brandon Jonesd1049182018-03-28 10:02:20 -07004507 SetRobustLengthParam(length, numParams);
4508
Geoff Langff5b2d52016-09-07 11:32:23 -04004509 return true;
4510}
4511
Geoff Lang740d9022016-10-07 11:20:52 -04004512bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4513 GLenum target,
4514 GLenum pname,
4515 GLsizei bufSize,
4516 GLsizei *length,
4517 GLint *params)
4518{
4519 if (!ValidateRobustEntryPoint(context, bufSize))
4520 {
4521 return false;
4522 }
4523
Brandon Jonesd1049182018-03-28 10:02:20 -07004524 GLsizei numParams = 0;
4525
4526 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004527 {
4528 return false;
4529 }
4530
Brandon Jonesd1049182018-03-28 10:02:20 -07004531 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004532 {
4533 return false;
4534 }
4535
Brandon Jonesd1049182018-03-28 10:02:20 -07004536 SetRobustLengthParam(length, numParams);
4537
Geoff Lang740d9022016-10-07 11:20:52 -04004538 return true;
4539}
4540
Geoff Langd7d0ed32016-10-07 11:33:51 -04004541bool ValidateGetShaderivRobustANGLE(Context *context,
4542 GLuint shader,
4543 GLenum pname,
4544 GLsizei bufSize,
4545 GLsizei *length,
4546 GLint *params)
4547{
4548 if (!ValidateRobustEntryPoint(context, bufSize))
4549 {
4550 return false;
4551 }
4552
Brandon Jonesd1049182018-03-28 10:02:20 -07004553 GLsizei numParams = 0;
4554
4555 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004556 {
4557 return false;
4558 }
4559
Brandon Jonesd1049182018-03-28 10:02:20 -07004560 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004561 {
4562 return false;
4563 }
4564
Brandon Jonesd1049182018-03-28 10:02:20 -07004565 SetRobustLengthParam(length, numParams);
4566
Geoff Langd7d0ed32016-10-07 11:33:51 -04004567 return true;
4568}
4569
Geoff Langc1984ed2016-10-07 12:41:00 -04004570bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004571 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004572 GLenum pname,
4573 GLsizei bufSize,
4574 GLsizei *length,
4575 GLfloat *params)
4576{
4577 if (!ValidateRobustEntryPoint(context, bufSize))
4578 {
4579 return false;
4580 }
4581
Brandon Jonesd1049182018-03-28 10:02:20 -07004582 GLsizei numParams = 0;
4583
4584 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004585 {
4586 return false;
4587 }
4588
Brandon Jonesd1049182018-03-28 10:02:20 -07004589 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004590 {
4591 return false;
4592 }
4593
Brandon Jonesd1049182018-03-28 10:02:20 -07004594 SetRobustLengthParam(length, numParams);
4595
Geoff Langc1984ed2016-10-07 12:41:00 -04004596 return true;
4597}
4598
Geoff Langc1984ed2016-10-07 12:41:00 -04004599bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004600 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004601 GLenum pname,
4602 GLsizei bufSize,
4603 GLsizei *length,
4604 GLint *params)
4605{
Brandon Jonesd1049182018-03-28 10:02:20 -07004606
Geoff Langc1984ed2016-10-07 12:41:00 -04004607 if (!ValidateRobustEntryPoint(context, bufSize))
4608 {
4609 return false;
4610 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004611 GLsizei numParams = 0;
4612 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004613 {
4614 return false;
4615 }
4616
Brandon Jonesd1049182018-03-28 10:02:20 -07004617 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004618 {
4619 return false;
4620 }
4621
Brandon Jonesd1049182018-03-28 10:02:20 -07004622 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004623 return true;
4624}
4625
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004626bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4627 TextureType target,
4628 GLenum pname,
4629 GLsizei bufSize,
4630 GLsizei *length,
4631 GLint *params)
4632{
4633 UNIMPLEMENTED();
4634 return false;
4635}
4636
4637bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4638 TextureType target,
4639 GLenum pname,
4640 GLsizei bufSize,
4641 GLsizei *length,
4642 GLuint *params)
4643{
4644 UNIMPLEMENTED();
4645 return false;
4646}
4647
Geoff Langc1984ed2016-10-07 12:41:00 -04004648bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004649 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004650 GLenum pname,
4651 GLsizei bufSize,
4652 const GLfloat *params)
4653{
4654 if (!ValidateRobustEntryPoint(context, bufSize))
4655 {
4656 return false;
4657 }
4658
4659 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4660}
4661
Geoff Langc1984ed2016-10-07 12:41:00 -04004662bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004663 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004664 GLenum pname,
4665 GLsizei bufSize,
4666 const GLint *params)
4667{
4668 if (!ValidateRobustEntryPoint(context, bufSize))
4669 {
4670 return false;
4671 }
4672
4673 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4674}
4675
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004676bool ValidateTexParameterIivRobustANGLE(Context *context,
4677 TextureType target,
4678 GLenum pname,
4679 GLsizei bufSize,
4680 const GLint *params)
4681{
4682 UNIMPLEMENTED();
4683 return false;
4684}
4685
4686bool ValidateTexParameterIuivRobustANGLE(Context *context,
4687 TextureType target,
4688 GLenum pname,
4689 GLsizei bufSize,
4690 const GLuint *params)
4691{
4692 UNIMPLEMENTED();
4693 return false;
4694}
4695
Geoff Langc1984ed2016-10-07 12:41:00 -04004696bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4697 GLuint sampler,
4698 GLenum pname,
4699 GLuint bufSize,
4700 GLsizei *length,
4701 GLfloat *params)
4702{
4703 if (!ValidateRobustEntryPoint(context, bufSize))
4704 {
4705 return false;
4706 }
4707
Brandon Jonesd1049182018-03-28 10:02:20 -07004708 GLsizei numParams = 0;
4709
4710 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004711 {
4712 return false;
4713 }
4714
Brandon Jonesd1049182018-03-28 10:02:20 -07004715 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004716 {
4717 return false;
4718 }
4719
Brandon Jonesd1049182018-03-28 10:02:20 -07004720 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004721 return true;
4722}
4723
Geoff Langc1984ed2016-10-07 12:41:00 -04004724bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4725 GLuint sampler,
4726 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004727 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004728 GLsizei *length,
4729 GLint *params)
4730{
4731 if (!ValidateRobustEntryPoint(context, bufSize))
4732 {
4733 return false;
4734 }
4735
Brandon Jonesd1049182018-03-28 10:02:20 -07004736 GLsizei numParams = 0;
4737
4738 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004739 {
4740 return false;
4741 }
4742
Brandon Jonesd1049182018-03-28 10:02:20 -07004743 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004744 {
4745 return false;
4746 }
4747
Brandon Jonesd1049182018-03-28 10:02:20 -07004748 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004749 return true;
4750}
4751
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004752bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4753 GLuint sampler,
4754 GLenum pname,
4755 GLsizei bufSize,
4756 GLsizei *length,
4757 GLint *params)
4758{
4759 UNIMPLEMENTED();
4760 return false;
4761}
4762
4763bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4764 GLuint sampler,
4765 GLenum pname,
4766 GLsizei bufSize,
4767 GLsizei *length,
4768 GLuint *params)
4769{
4770 UNIMPLEMENTED();
4771 return false;
4772}
4773
Geoff Langc1984ed2016-10-07 12:41:00 -04004774bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4775 GLuint sampler,
4776 GLenum pname,
4777 GLsizei bufSize,
4778 const GLfloat *params)
4779{
4780 if (!ValidateRobustEntryPoint(context, bufSize))
4781 {
4782 return false;
4783 }
4784
4785 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4786}
4787
Geoff Langc1984ed2016-10-07 12:41:00 -04004788bool ValidateSamplerParameterivRobustANGLE(Context *context,
4789 GLuint sampler,
4790 GLenum pname,
4791 GLsizei bufSize,
4792 const GLint *params)
4793{
4794 if (!ValidateRobustEntryPoint(context, bufSize))
4795 {
4796 return false;
4797 }
4798
4799 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4800}
4801
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004802bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4803 GLuint sampler,
4804 GLenum pname,
4805 GLsizei bufSize,
4806 const GLint *param)
4807{
4808 UNIMPLEMENTED();
4809 return false;
4810}
4811
4812bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4813 GLuint sampler,
4814 GLenum pname,
4815 GLsizei bufSize,
4816 const GLuint *param)
4817{
4818 UNIMPLEMENTED();
4819 return false;
4820}
4821
Geoff Lang0b031062016-10-13 14:30:04 -04004822bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4823 GLuint index,
4824 GLenum pname,
4825 GLsizei bufSize,
4826 GLsizei *length,
4827 GLfloat *params)
4828{
4829 if (!ValidateRobustEntryPoint(context, bufSize))
4830 {
4831 return false;
4832 }
4833
Brandon Jonesd1049182018-03-28 10:02:20 -07004834 GLsizei writeLength = 0;
4835
4836 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004837 {
4838 return false;
4839 }
4840
Brandon Jonesd1049182018-03-28 10:02:20 -07004841 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004842 {
4843 return false;
4844 }
4845
Brandon Jonesd1049182018-03-28 10:02:20 -07004846 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004847 return true;
4848}
4849
Geoff Lang0b031062016-10-13 14:30:04 -04004850bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4851 GLuint index,
4852 GLenum pname,
4853 GLsizei bufSize,
4854 GLsizei *length,
4855 GLint *params)
4856{
4857 if (!ValidateRobustEntryPoint(context, bufSize))
4858 {
4859 return false;
4860 }
4861
Brandon Jonesd1049182018-03-28 10:02:20 -07004862 GLsizei writeLength = 0;
4863
4864 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004865 {
4866 return false;
4867 }
4868
Brandon Jonesd1049182018-03-28 10:02:20 -07004869 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004870 {
4871 return false;
4872 }
4873
Brandon Jonesd1049182018-03-28 10:02:20 -07004874 SetRobustLengthParam(length, writeLength);
4875
Geoff Lang0b031062016-10-13 14:30:04 -04004876 return true;
4877}
4878
Geoff Lang0b031062016-10-13 14:30:04 -04004879bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4880 GLuint index,
4881 GLenum pname,
4882 GLsizei bufSize,
4883 GLsizei *length,
4884 void **pointer)
4885{
4886 if (!ValidateRobustEntryPoint(context, bufSize))
4887 {
4888 return false;
4889 }
4890
Brandon Jonesd1049182018-03-28 10:02:20 -07004891 GLsizei writeLength = 0;
4892
4893 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004894 {
4895 return false;
4896 }
4897
Brandon Jonesd1049182018-03-28 10:02:20 -07004898 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004899 {
4900 return false;
4901 }
4902
Brandon Jonesd1049182018-03-28 10:02:20 -07004903 SetRobustLengthParam(length, writeLength);
4904
Geoff Lang0b031062016-10-13 14:30:04 -04004905 return true;
4906}
4907
Geoff Lang0b031062016-10-13 14:30:04 -04004908bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4909 GLuint index,
4910 GLenum pname,
4911 GLsizei bufSize,
4912 GLsizei *length,
4913 GLint *params)
4914{
4915 if (!ValidateRobustEntryPoint(context, bufSize))
4916 {
4917 return false;
4918 }
4919
Brandon Jonesd1049182018-03-28 10:02:20 -07004920 GLsizei writeLength = 0;
4921
4922 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004923 {
4924 return false;
4925 }
4926
Brandon Jonesd1049182018-03-28 10:02:20 -07004927 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004928 {
4929 return false;
4930 }
4931
Brandon Jonesd1049182018-03-28 10:02:20 -07004932 SetRobustLengthParam(length, writeLength);
4933
Geoff Lang0b031062016-10-13 14:30:04 -04004934 return true;
4935}
4936
Geoff Lang0b031062016-10-13 14:30:04 -04004937bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4938 GLuint index,
4939 GLenum pname,
4940 GLsizei bufSize,
4941 GLsizei *length,
4942 GLuint *params)
4943{
4944 if (!ValidateRobustEntryPoint(context, bufSize))
4945 {
4946 return false;
4947 }
4948
Brandon Jonesd1049182018-03-28 10:02:20 -07004949 GLsizei writeLength = 0;
4950
4951 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004952 {
4953 return false;
4954 }
4955
Brandon Jonesd1049182018-03-28 10:02:20 -07004956 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004957 {
4958 return false;
4959 }
4960
Brandon Jonesd1049182018-03-28 10:02:20 -07004961 SetRobustLengthParam(length, writeLength);
4962
Geoff Lang0b031062016-10-13 14:30:04 -04004963 return true;
4964}
4965
Geoff Lang6899b872016-10-14 11:30:13 -04004966bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4967 GLuint program,
4968 GLuint uniformBlockIndex,
4969 GLenum pname,
4970 GLsizei bufSize,
4971 GLsizei *length,
4972 GLint *params)
4973{
4974 if (!ValidateRobustEntryPoint(context, bufSize))
4975 {
4976 return false;
4977 }
4978
Brandon Jonesd1049182018-03-28 10:02:20 -07004979 GLsizei writeLength = 0;
4980
4981 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4982 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004983 {
4984 return false;
4985 }
4986
Brandon Jonesd1049182018-03-28 10:02:20 -07004987 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004988 {
4989 return false;
4990 }
4991
Brandon Jonesd1049182018-03-28 10:02:20 -07004992 SetRobustLengthParam(length, writeLength);
4993
Geoff Lang6899b872016-10-14 11:30:13 -04004994 return true;
4995}
4996
Brandon Jones416aaf92018-04-10 08:10:16 -07004997bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004998 GLenum target,
4999 GLenum internalformat,
5000 GLenum pname,
5001 GLsizei bufSize,
5002 GLsizei *length,
5003 GLint *params)
5004{
5005 if (!ValidateRobustEntryPoint(context, bufSize))
5006 {
5007 return false;
5008 }
5009
Brandon Jonesd1049182018-03-28 10:02:20 -07005010 GLsizei numParams = 0;
5011
5012 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5013 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005014 {
5015 return false;
5016 }
5017
Brandon Jonesd1049182018-03-28 10:02:20 -07005018 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005019 {
5020 return false;
5021 }
5022
Brandon Jonesd1049182018-03-28 10:02:20 -07005023 SetRobustLengthParam(length, numParams);
5024
Geoff Lang0a9661f2016-10-20 10:59:20 -07005025 return true;
5026}
5027
Jamie Madill5b772312018-03-08 20:28:32 -05005028bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005029 GLuint attribIndex,
5030 GLint size,
5031 GLenum type,
5032 GLboolean pureInteger)
5033{
5034 const Caps &caps = context->getCaps();
5035 if (attribIndex >= caps.maxVertexAttributes)
5036 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005037 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005038 return false;
5039 }
5040
5041 if (size < 1 || size > 4)
5042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005043 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005044 return false;
Shao80957d92017-02-20 21:25:59 +08005045 }
5046
5047 switch (type)
5048 {
5049 case GL_BYTE:
5050 case GL_UNSIGNED_BYTE:
5051 case GL_SHORT:
5052 case GL_UNSIGNED_SHORT:
5053 break;
5054
5055 case GL_INT:
5056 case GL_UNSIGNED_INT:
5057 if (context->getClientMajorVersion() < 3)
5058 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005059 context->handleError(InvalidEnum()
5060 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005061 return false;
5062 }
5063 break;
5064
5065 case GL_FIXED:
5066 case GL_FLOAT:
5067 if (pureInteger)
5068 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005069 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005070 return false;
5071 }
5072 break;
5073
5074 case GL_HALF_FLOAT:
5075 if (context->getClientMajorVersion() < 3)
5076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005077 context->handleError(InvalidEnum()
5078 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005079 return false;
5080 }
5081 if (pureInteger)
5082 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005083 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005084 return false;
5085 }
5086 break;
5087
5088 case GL_INT_2_10_10_10_REV:
5089 case GL_UNSIGNED_INT_2_10_10_10_REV:
5090 if (context->getClientMajorVersion() < 3)
5091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005092 context->handleError(InvalidEnum()
5093 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005094 return false;
5095 }
5096 if (pureInteger)
5097 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005098 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005099 return false;
5100 }
5101 if (size != 4)
5102 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005103 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5104 "UNSIGNED_INT_2_10_10_10_REV and "
5105 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005106 return false;
5107 }
5108 break;
5109
5110 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005112 return false;
5113 }
5114
5115 return true;
5116}
5117
Geoff Lang76e65652017-03-27 14:58:02 -04005118// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5119// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5120// specified clear value and the type of a buffer that is being cleared generates an
5121// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005122bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005123 GLint drawbuffer,
5124 const GLenum *validComponentTypes,
5125 size_t validComponentTypeCount)
5126{
5127 const FramebufferAttachment *attachment =
5128 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5129 if (attachment)
5130 {
5131 GLenum componentType = attachment->getFormat().info->componentType;
5132 const GLenum *end = validComponentTypes + validComponentTypeCount;
5133 if (std::find(validComponentTypes, end, componentType) == end)
5134 {
5135 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005136 InvalidOperation()
5137 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005138 return false;
5139 }
5140 }
5141
5142 return true;
5143}
5144
Jamie Madill5b772312018-03-08 20:28:32 -05005145bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005146{
5147 if (!ValidateRobustEntryPoint(context, dataSize))
5148 {
5149 return false;
5150 }
5151
Corentin Wallez336129f2017-10-17 15:55:40 -04005152 gl::Buffer *pixelUnpackBuffer =
5153 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005154 if (pixelUnpackBuffer == nullptr)
5155 {
5156 if (dataSize < imageSize)
5157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005158 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005159 }
5160 }
5161 return true;
5162}
5163
Jamie Madill5b772312018-03-08 20:28:32 -05005164bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005165 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005166 GLenum pname,
5167 bool pointerVersion,
5168 GLsizei *numParams)
5169{
5170 if (numParams)
5171 {
5172 *numParams = 0;
5173 }
5174
Corentin Walleze4477002017-12-01 14:39:58 -05005175 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005177 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005178 return false;
5179 }
5180
5181 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5182 if (!buffer)
5183 {
5184 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005185 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005186 return false;
5187 }
5188
5189 const Extensions &extensions = context->getExtensions();
5190
5191 switch (pname)
5192 {
5193 case GL_BUFFER_USAGE:
5194 case GL_BUFFER_SIZE:
5195 break;
5196
5197 case GL_BUFFER_ACCESS_OES:
5198 if (!extensions.mapBuffer)
5199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005200 context->handleError(InvalidEnum()
5201 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005202 return false;
5203 }
5204 break;
5205
5206 case GL_BUFFER_MAPPED:
5207 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5208 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5209 !extensions.mapBufferRange)
5210 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005211 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5212 "GL_OES_mapbuffer or "
5213 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005214 return false;
5215 }
5216 break;
5217
5218 case GL_BUFFER_MAP_POINTER:
5219 if (!pointerVersion)
5220 {
5221 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005222 InvalidEnum()
5223 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005224 return false;
5225 }
5226 break;
5227
5228 case GL_BUFFER_ACCESS_FLAGS:
5229 case GL_BUFFER_MAP_OFFSET:
5230 case GL_BUFFER_MAP_LENGTH:
5231 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005233 context->handleError(InvalidEnum()
5234 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005235 return false;
5236 }
5237 break;
5238
5239 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005240 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005241 return false;
5242 }
5243
5244 // All buffer parameter queries return one value.
5245 if (numParams)
5246 {
5247 *numParams = 1;
5248 }
5249
5250 return true;
5251}
5252
5253bool ValidateGetRenderbufferParameterivBase(Context *context,
5254 GLenum target,
5255 GLenum pname,
5256 GLsizei *length)
5257{
5258 if (length)
5259 {
5260 *length = 0;
5261 }
5262
5263 if (target != GL_RENDERBUFFER)
5264 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005265 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005266 return false;
5267 }
5268
5269 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5270 if (renderbuffer == nullptr)
5271 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005272 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005273 return false;
5274 }
5275
5276 switch (pname)
5277 {
5278 case GL_RENDERBUFFER_WIDTH:
5279 case GL_RENDERBUFFER_HEIGHT:
5280 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5281 case GL_RENDERBUFFER_RED_SIZE:
5282 case GL_RENDERBUFFER_GREEN_SIZE:
5283 case GL_RENDERBUFFER_BLUE_SIZE:
5284 case GL_RENDERBUFFER_ALPHA_SIZE:
5285 case GL_RENDERBUFFER_DEPTH_SIZE:
5286 case GL_RENDERBUFFER_STENCIL_SIZE:
5287 break;
5288
5289 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5290 if (!context->getExtensions().framebufferMultisample)
5291 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005292 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295 break;
5296
5297 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005298 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005299 return false;
5300 }
5301
5302 if (length)
5303 {
5304 *length = 1;
5305 }
5306 return true;
5307}
5308
5309bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5310{
5311 if (length)
5312 {
5313 *length = 0;
5314 }
5315
5316 if (GetValidShader(context, shader) == nullptr)
5317 {
5318 return false;
5319 }
5320
5321 switch (pname)
5322 {
5323 case GL_SHADER_TYPE:
5324 case GL_DELETE_STATUS:
5325 case GL_COMPILE_STATUS:
5326 case GL_INFO_LOG_LENGTH:
5327 case GL_SHADER_SOURCE_LENGTH:
5328 break;
5329
5330 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5331 if (!context->getExtensions().translatedShaderSource)
5332 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005333 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005334 return false;
5335 }
5336 break;
5337
5338 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005340 return false;
5341 }
5342
5343 if (length)
5344 {
5345 *length = 1;
5346 }
5347 return true;
5348}
5349
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005350bool ValidateGetTexParameterBase(Context *context,
5351 TextureType target,
5352 GLenum pname,
5353 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005354{
5355 if (length)
5356 {
5357 *length = 0;
5358 }
5359
5360 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5361 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005362 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005363 return false;
5364 }
5365
5366 if (context->getTargetTexture(target) == nullptr)
5367 {
5368 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005369 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005370 return false;
5371 }
5372
5373 switch (pname)
5374 {
5375 case GL_TEXTURE_MAG_FILTER:
5376 case GL_TEXTURE_MIN_FILTER:
5377 case GL_TEXTURE_WRAP_S:
5378 case GL_TEXTURE_WRAP_T:
5379 break;
5380
5381 case GL_TEXTURE_USAGE_ANGLE:
5382 if (!context->getExtensions().textureUsage)
5383 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005384 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005385 return false;
5386 }
5387 break;
5388
5389 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005390 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005391 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005392 return false;
5393 }
5394 break;
5395
5396 case GL_TEXTURE_IMMUTABLE_FORMAT:
5397 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5398 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005399 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005400 return false;
5401 }
5402 break;
5403
5404 case GL_TEXTURE_WRAP_R:
5405 case GL_TEXTURE_IMMUTABLE_LEVELS:
5406 case GL_TEXTURE_SWIZZLE_R:
5407 case GL_TEXTURE_SWIZZLE_G:
5408 case GL_TEXTURE_SWIZZLE_B:
5409 case GL_TEXTURE_SWIZZLE_A:
5410 case GL_TEXTURE_BASE_LEVEL:
5411 case GL_TEXTURE_MAX_LEVEL:
5412 case GL_TEXTURE_MIN_LOD:
5413 case GL_TEXTURE_MAX_LOD:
5414 case GL_TEXTURE_COMPARE_MODE:
5415 case GL_TEXTURE_COMPARE_FUNC:
5416 if (context->getClientMajorVersion() < 3)
5417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005418 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005419 return false;
5420 }
5421 break;
5422
5423 case GL_TEXTURE_SRGB_DECODE_EXT:
5424 if (!context->getExtensions().textureSRGBDecode)
5425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005426 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005427 return false;
5428 }
5429 break;
5430
Yunchao Hebacaa712018-01-30 14:01:39 +08005431 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5432 if (context->getClientVersion() < Version(3, 1))
5433 {
5434 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5435 return false;
5436 }
5437 break;
5438
Jamie Madillbe849e42017-05-02 15:49:00 -04005439 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005440 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 return false;
5442 }
5443
5444 if (length)
5445 {
5446 *length = 1;
5447 }
5448 return true;
5449}
5450
5451bool ValidateGetVertexAttribBase(Context *context,
5452 GLuint index,
5453 GLenum pname,
5454 GLsizei *length,
5455 bool pointer,
5456 bool pureIntegerEntryPoint)
5457{
5458 if (length)
5459 {
5460 *length = 0;
5461 }
5462
5463 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005465 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005466 return false;
5467 }
5468
5469 if (index >= context->getCaps().maxVertexAttributes)
5470 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005471 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005472 return false;
5473 }
5474
5475 if (pointer)
5476 {
5477 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5478 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005479 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005480 return false;
5481 }
5482 }
5483 else
5484 {
5485 switch (pname)
5486 {
5487 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5488 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5489 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5490 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5491 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5492 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5493 case GL_CURRENT_VERTEX_ATTRIB:
5494 break;
5495
5496 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5497 static_assert(
5498 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5499 "ANGLE extension enums not equal to GL enums.");
5500 if (context->getClientMajorVersion() < 3 &&
5501 !context->getExtensions().instancedArrays)
5502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005503 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5504 "requires OpenGL ES 3.0 or "
5505 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005506 return false;
5507 }
5508 break;
5509
5510 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5511 if (context->getClientMajorVersion() < 3)
5512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005513 context->handleError(
5514 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005515 return false;
5516 }
5517 break;
5518
5519 case GL_VERTEX_ATTRIB_BINDING:
5520 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5521 if (context->getClientVersion() < ES_3_1)
5522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005523 context->handleError(InvalidEnum()
5524 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005525 return false;
5526 }
5527 break;
5528
5529 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005530 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005531 return false;
5532 }
5533 }
5534
5535 if (length)
5536 {
5537 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5538 {
5539 *length = 4;
5540 }
5541 else
5542 {
5543 *length = 1;
5544 }
5545 }
5546
5547 return true;
5548}
5549
Jamie Madill4928b7c2017-06-20 12:57:39 -04005550bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005551 GLint x,
5552 GLint y,
5553 GLsizei width,
5554 GLsizei height,
5555 GLenum format,
5556 GLenum type,
5557 GLsizei bufSize,
5558 GLsizei *length,
5559 GLsizei *columns,
5560 GLsizei *rows,
5561 void *pixels)
5562{
5563 if (length != nullptr)
5564 {
5565 *length = 0;
5566 }
5567 if (rows != nullptr)
5568 {
5569 *rows = 0;
5570 }
5571 if (columns != nullptr)
5572 {
5573 *columns = 0;
5574 }
5575
5576 if (width < 0 || height < 0)
5577 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005578 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005579 return false;
5580 }
5581
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005582 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005583
Jamie Madill427064d2018-04-13 16:20:34 -04005584 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005585 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 return false;
5587 }
5588
Jamie Madille98b1b52018-03-08 09:47:23 -05005589 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005590 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005591 return false;
5592 }
5593
Jamie Madill690c8eb2018-03-12 15:20:03 -04005594 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005595 ASSERT(framebuffer);
5596
5597 if (framebuffer->getReadBufferState() == GL_NONE)
5598 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005599 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005600 return false;
5601 }
5602
5603 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5604 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5605 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5606 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5607 // situation is an application error that would lead to a crash in ANGLE.
5608 if (readBuffer == nullptr)
5609 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005610 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005611 return false;
5612 }
5613
Martin Radev28031682017-07-28 14:47:56 +03005614 // ANGLE_multiview, Revision 1:
5615 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5616 // current read framebuffer is not NONE.
5617 if (readBuffer->getMultiviewLayout() != GL_NONE)
5618 {
5619 context->handleError(InvalidFramebufferOperation()
5620 << "Attempting to read from a multi-view framebuffer.");
5621 return false;
5622 }
5623
Geoff Lang280ba992017-04-18 16:30:58 -04005624 if (context->getExtensions().webglCompatibility)
5625 {
5626 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5627 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5628 // and type before validating the combination of format and type. However, the
5629 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5630 // verifies that GL_INVALID_OPERATION is generated.
5631 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5632 // dEQP/WebGL.
5633 if (!ValidReadPixelsFormatEnum(context, format))
5634 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005635 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005636 return false;
5637 }
5638
5639 if (!ValidReadPixelsTypeEnum(context, type))
5640 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005641 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005642 return false;
5643 }
5644 }
5645
Jamie Madill690c8eb2018-03-12 15:20:03 -04005646 GLenum currentFormat = GL_NONE;
5647 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5648
5649 GLenum currentType = GL_NONE;
5650 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5651
Jamie Madillbe849e42017-05-02 15:49:00 -04005652 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5653
5654 bool validFormatTypeCombination =
5655 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5656
5657 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5658 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005659 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 return false;
5661 }
5662
5663 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005664 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005665 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5666 {
5667 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005668 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005669 return false;
5670 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005671 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5672 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5673 {
5674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5675 return false;
5676 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005677
5678 // .. the data would be packed to the buffer object such that the memory writes required
5679 // would exceed the data store size.
5680 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5681 const gl::Extents size(width, height, 1);
5682 const auto &pack = context->getGLState().getPackState();
5683
5684 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5685 if (endByteOrErr.isError())
5686 {
5687 context->handleError(endByteOrErr.getError());
5688 return false;
5689 }
5690
5691 size_t endByte = endByteOrErr.getResult();
5692 if (bufSize >= 0)
5693 {
5694 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5695 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005696 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005697 return false;
5698 }
5699 }
5700
5701 if (pixelPackBuffer != nullptr)
5702 {
5703 CheckedNumeric<size_t> checkedEndByte(endByte);
5704 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5705 checkedEndByte += checkedOffset;
5706
5707 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5708 {
5709 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005710 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005711 return false;
5712 }
5713 }
5714
5715 if (pixelPackBuffer == nullptr && length != nullptr)
5716 {
5717 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5718 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005719 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005720 return false;
5721 }
5722
5723 *length = static_cast<GLsizei>(endByte);
5724 }
5725
Geoff Langa953b522018-02-21 16:56:23 -05005726 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005727 angle::CheckedNumeric<int> clippedExtent(length);
5728 if (start < 0)
5729 {
5730 // "subtract" the area that is less than 0
5731 clippedExtent += start;
5732 }
5733
Geoff Langa953b522018-02-21 16:56:23 -05005734 angle::CheckedNumeric<int> readExtent = start;
5735 readExtent += length;
5736 if (!readExtent.IsValid())
5737 {
5738 return false;
5739 }
5740
5741 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005742 {
5743 // Subtract the region to the right of the read buffer
5744 clippedExtent -= (readExtent - bufferSize);
5745 }
5746
5747 if (!clippedExtent.IsValid())
5748 {
Geoff Langa953b522018-02-21 16:56:23 -05005749 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005750 }
5751
Geoff Langa953b522018-02-21 16:56:23 -05005752 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5753 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005754 };
5755
Geoff Langa953b522018-02-21 16:56:23 -05005756 GLsizei writtenColumns = 0;
5757 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5758 {
5759 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5760 return false;
5761 }
5762
5763 GLsizei writtenRows = 0;
5764 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5765 {
5766 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5767 return false;
5768 }
5769
Jamie Madillbe849e42017-05-02 15:49:00 -04005770 if (columns != nullptr)
5771 {
Geoff Langa953b522018-02-21 16:56:23 -05005772 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005773 }
5774
5775 if (rows != nullptr)
5776 {
Geoff Langa953b522018-02-21 16:56:23 -05005777 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005778 }
5779
5780 return true;
5781}
5782
5783template <typename ParamType>
5784bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005785 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005786 GLenum pname,
5787 GLsizei bufSize,
5788 const ParamType *params)
5789{
5790 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5791 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005792 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005793 return false;
5794 }
5795
5796 if (context->getTargetTexture(target) == nullptr)
5797 {
5798 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005799 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005800 return false;
5801 }
5802
5803 const GLsizei minBufSize = 1;
5804 if (bufSize >= 0 && bufSize < minBufSize)
5805 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 return false;
5808 }
5809
5810 switch (pname)
5811 {
5812 case GL_TEXTURE_WRAP_R:
5813 case GL_TEXTURE_SWIZZLE_R:
5814 case GL_TEXTURE_SWIZZLE_G:
5815 case GL_TEXTURE_SWIZZLE_B:
5816 case GL_TEXTURE_SWIZZLE_A:
5817 case GL_TEXTURE_BASE_LEVEL:
5818 case GL_TEXTURE_MAX_LEVEL:
5819 case GL_TEXTURE_COMPARE_MODE:
5820 case GL_TEXTURE_COMPARE_FUNC:
5821 case GL_TEXTURE_MIN_LOD:
5822 case GL_TEXTURE_MAX_LOD:
5823 if (context->getClientMajorVersion() < 3)
5824 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005825 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005826 return false;
5827 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005828 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005830 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5831 "available without "
5832 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005833 return false;
5834 }
5835 break;
5836
5837 default:
5838 break;
5839 }
5840
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005841 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005842 {
5843 switch (pname)
5844 {
5845 case GL_TEXTURE_MIN_FILTER:
5846 case GL_TEXTURE_MAG_FILTER:
5847 case GL_TEXTURE_WRAP_S:
5848 case GL_TEXTURE_WRAP_T:
5849 case GL_TEXTURE_WRAP_R:
5850 case GL_TEXTURE_MIN_LOD:
5851 case GL_TEXTURE_MAX_LOD:
5852 case GL_TEXTURE_COMPARE_MODE:
5853 case GL_TEXTURE_COMPARE_FUNC:
5854 context->handleError(InvalidEnum()
5855 << "Invalid parameter for 2D multisampled textures.");
5856 return false;
5857 }
5858 }
5859
Jamie Madillbe849e42017-05-02 15:49:00 -04005860 switch (pname)
5861 {
5862 case GL_TEXTURE_WRAP_S:
5863 case GL_TEXTURE_WRAP_T:
5864 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005865 {
5866 bool restrictedWrapModes =
5867 target == TextureType::External || target == TextureType::Rectangle;
5868 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005869 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005870 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005871 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005872 }
5873 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005874
5875 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005876 {
5877 bool restrictedMinFilter =
5878 target == TextureType::External || target == TextureType::Rectangle;
5879 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005880 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005881 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005882 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005883 }
5884 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005885
5886 case GL_TEXTURE_MAG_FILTER:
5887 if (!ValidateTextureMagFilterValue(context, params))
5888 {
5889 return false;
5890 }
5891 break;
5892
5893 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005894 if (!context->getExtensions().textureUsage)
5895 {
5896 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5897 return false;
5898 }
5899
Jamie Madillbe849e42017-05-02 15:49:00 -04005900 switch (ConvertToGLenum(params[0]))
5901 {
5902 case GL_NONE:
5903 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5904 break;
5905
5906 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005908 return false;
5909 }
5910 break;
5911
5912 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005913 {
5914 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5915 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005916 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005917 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005918 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005919 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5920 }
5921 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005922
5923 case GL_TEXTURE_MIN_LOD:
5924 case GL_TEXTURE_MAX_LOD:
5925 // any value is permissible
5926 break;
5927
5928 case GL_TEXTURE_COMPARE_MODE:
5929 if (!ValidateTextureCompareModeValue(context, params))
5930 {
5931 return false;
5932 }
5933 break;
5934
5935 case GL_TEXTURE_COMPARE_FUNC:
5936 if (!ValidateTextureCompareFuncValue(context, params))
5937 {
5938 return false;
5939 }
5940 break;
5941
5942 case GL_TEXTURE_SWIZZLE_R:
5943 case GL_TEXTURE_SWIZZLE_G:
5944 case GL_TEXTURE_SWIZZLE_B:
5945 case GL_TEXTURE_SWIZZLE_A:
5946 switch (ConvertToGLenum(params[0]))
5947 {
5948 case GL_RED:
5949 case GL_GREEN:
5950 case GL_BLUE:
5951 case GL_ALPHA:
5952 case GL_ZERO:
5953 case GL_ONE:
5954 break;
5955
5956 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005958 return false;
5959 }
5960 break;
5961
5962 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005963 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005965 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005966 return false;
5967 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005968 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005970 context->handleError(InvalidOperation()
5971 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005972 return false;
5973 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005974 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005975 {
5976 context->handleError(InvalidOperation()
5977 << "Base level must be 0 for multisampled textures.");
5978 return false;
5979 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005980 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005981 {
5982 context->handleError(InvalidOperation()
5983 << "Base level must be 0 for rectangle textures.");
5984 return false;
5985 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005986 break;
5987
5988 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005989 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005990 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005991 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005992 return false;
5993 }
5994 break;
5995
5996 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5997 if (context->getClientVersion() < Version(3, 1))
5998 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005999 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006000 return false;
6001 }
6002 switch (ConvertToGLenum(params[0]))
6003 {
6004 case GL_DEPTH_COMPONENT:
6005 case GL_STENCIL_INDEX:
6006 break;
6007
6008 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006009 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006010 return false;
6011 }
6012 break;
6013
6014 case GL_TEXTURE_SRGB_DECODE_EXT:
6015 if (!ValidateTextureSRGBDecodeValue(context, params))
6016 {
6017 return false;
6018 }
6019 break;
6020
6021 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006023 return false;
6024 }
6025
6026 return true;
6027}
6028
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006029template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6030template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006031
Jamie Madill5b772312018-03-08 20:28:32 -05006032bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006033{
6034 if (index >= MAX_VERTEX_ATTRIBS)
6035 {
6036 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6037 return false;
6038 }
6039
6040 return true;
6041}
6042
6043bool ValidateGetActiveUniformBlockivBase(Context *context,
6044 GLuint program,
6045 GLuint uniformBlockIndex,
6046 GLenum pname,
6047 GLsizei *length)
6048{
6049 if (length)
6050 {
6051 *length = 0;
6052 }
6053
6054 if (context->getClientMajorVersion() < 3)
6055 {
6056 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6057 return false;
6058 }
6059
6060 Program *programObject = GetValidProgram(context, program);
6061 if (!programObject)
6062 {
6063 return false;
6064 }
6065
6066 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6067 {
6068 context->handleError(InvalidValue()
6069 << "uniformBlockIndex exceeds active uniform block count.");
6070 return false;
6071 }
6072
6073 switch (pname)
6074 {
6075 case GL_UNIFORM_BLOCK_BINDING:
6076 case GL_UNIFORM_BLOCK_DATA_SIZE:
6077 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6078 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6079 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6080 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6081 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6082 break;
6083
6084 default:
6085 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6086 return false;
6087 }
6088
6089 if (length)
6090 {
6091 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6092 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006093 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006094 programObject->getUniformBlockByIndex(uniformBlockIndex);
6095 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6096 }
6097 else
6098 {
6099 *length = 1;
6100 }
6101 }
6102
6103 return true;
6104}
6105
Jamie Madill9696d072017-08-26 23:19:57 -04006106template <typename ParamType>
6107bool ValidateSamplerParameterBase(Context *context,
6108 GLuint sampler,
6109 GLenum pname,
6110 GLsizei bufSize,
6111 ParamType *params)
6112{
6113 if (context->getClientMajorVersion() < 3)
6114 {
6115 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6116 return false;
6117 }
6118
6119 if (!context->isSampler(sampler))
6120 {
6121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6122 return false;
6123 }
6124
6125 const GLsizei minBufSize = 1;
6126 if (bufSize >= 0 && bufSize < minBufSize)
6127 {
6128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6129 return false;
6130 }
6131
6132 switch (pname)
6133 {
6134 case GL_TEXTURE_WRAP_S:
6135 case GL_TEXTURE_WRAP_T:
6136 case GL_TEXTURE_WRAP_R:
6137 if (!ValidateTextureWrapModeValue(context, params, false))
6138 {
6139 return false;
6140 }
6141 break;
6142
6143 case GL_TEXTURE_MIN_FILTER:
6144 if (!ValidateTextureMinFilterValue(context, params, false))
6145 {
6146 return false;
6147 }
6148 break;
6149
6150 case GL_TEXTURE_MAG_FILTER:
6151 if (!ValidateTextureMagFilterValue(context, params))
6152 {
6153 return false;
6154 }
6155 break;
6156
6157 case GL_TEXTURE_MIN_LOD:
6158 case GL_TEXTURE_MAX_LOD:
6159 // any value is permissible
6160 break;
6161
6162 case GL_TEXTURE_COMPARE_MODE:
6163 if (!ValidateTextureCompareModeValue(context, params))
6164 {
6165 return false;
6166 }
6167 break;
6168
6169 case GL_TEXTURE_COMPARE_FUNC:
6170 if (!ValidateTextureCompareFuncValue(context, params))
6171 {
6172 return false;
6173 }
6174 break;
6175
6176 case GL_TEXTURE_SRGB_DECODE_EXT:
6177 if (!ValidateTextureSRGBDecodeValue(context, params))
6178 {
6179 return false;
6180 }
6181 break;
6182
Luc Ferron1b1a8642018-01-23 15:12:01 -05006183 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6184 {
6185 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6186 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6187 {
6188 return false;
6189 }
6190 }
6191 break;
6192
Jamie Madill9696d072017-08-26 23:19:57 -04006193 default:
6194 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6195 return false;
6196 }
6197
6198 return true;
6199}
6200
6201template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6202template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6203
6204bool ValidateGetSamplerParameterBase(Context *context,
6205 GLuint sampler,
6206 GLenum pname,
6207 GLsizei *length)
6208{
6209 if (length)
6210 {
6211 *length = 0;
6212 }
6213
6214 if (context->getClientMajorVersion() < 3)
6215 {
6216 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6217 return false;
6218 }
6219
6220 if (!context->isSampler(sampler))
6221 {
6222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6223 return false;
6224 }
6225
6226 switch (pname)
6227 {
6228 case GL_TEXTURE_WRAP_S:
6229 case GL_TEXTURE_WRAP_T:
6230 case GL_TEXTURE_WRAP_R:
6231 case GL_TEXTURE_MIN_FILTER:
6232 case GL_TEXTURE_MAG_FILTER:
6233 case GL_TEXTURE_MIN_LOD:
6234 case GL_TEXTURE_MAX_LOD:
6235 case GL_TEXTURE_COMPARE_MODE:
6236 case GL_TEXTURE_COMPARE_FUNC:
6237 break;
6238
Luc Ferron1b1a8642018-01-23 15:12:01 -05006239 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6240 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6241 {
6242 return false;
6243 }
6244 break;
6245
Jamie Madill9696d072017-08-26 23:19:57 -04006246 case GL_TEXTURE_SRGB_DECODE_EXT:
6247 if (!context->getExtensions().textureSRGBDecode)
6248 {
6249 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6250 return false;
6251 }
6252 break;
6253
6254 default:
6255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6256 return false;
6257 }
6258
6259 if (length)
6260 {
6261 *length = 1;
6262 }
6263 return true;
6264}
6265
6266bool ValidateGetInternalFormativBase(Context *context,
6267 GLenum target,
6268 GLenum internalformat,
6269 GLenum pname,
6270 GLsizei bufSize,
6271 GLsizei *numParams)
6272{
6273 if (numParams)
6274 {
6275 *numParams = 0;
6276 }
6277
6278 if (context->getClientMajorVersion() < 3)
6279 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006281 return false;
6282 }
6283
6284 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6285 if (!formatCaps.renderable)
6286 {
6287 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6288 return false;
6289 }
6290
6291 switch (target)
6292 {
6293 case GL_RENDERBUFFER:
6294 break;
6295
6296 case GL_TEXTURE_2D_MULTISAMPLE:
6297 if (context->getClientVersion() < ES_3_1)
6298 {
6299 context->handleError(InvalidOperation()
6300 << "Texture target requires at least OpenGL ES 3.1.");
6301 return false;
6302 }
6303 break;
6304
6305 default:
6306 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6307 return false;
6308 }
6309
6310 if (bufSize < 0)
6311 {
6312 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6313 return false;
6314 }
6315
6316 GLsizei maxWriteParams = 0;
6317 switch (pname)
6318 {
6319 case GL_NUM_SAMPLE_COUNTS:
6320 maxWriteParams = 1;
6321 break;
6322
6323 case GL_SAMPLES:
6324 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6325 break;
6326
6327 default:
6328 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6329 return false;
6330 }
6331
6332 if (numParams)
6333 {
6334 // glGetInternalFormativ will not overflow bufSize
6335 *numParams = std::min(bufSize, maxWriteParams);
6336 }
6337
6338 return true;
6339}
6340
Jamie Madille98b1b52018-03-08 09:47:23 -05006341bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6342{
Jamie Madill427064d2018-04-13 16:20:34 -04006343 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006344 {
6345 context->handleError(InvalidOperation());
6346 return false;
6347 }
6348 return true;
6349}
6350
Lingfeng Yang038dd532018-03-29 17:31:52 -07006351bool ValidateMultitextureUnit(Context *context, GLenum texture)
6352{
6353 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6354 {
6355 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6356 return false;
6357 }
6358 return true;
6359}
6360
Jamie Madillc29968b2016-01-20 11:17:23 -05006361} // namespace gl